| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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 12 matching lines...) Expand all Loading... |
| 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 EAX. | 29 // on the stack and return the result in a fixed register EAX. |
| 30 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 30 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
| 31 const intptr_t kNumInputs = 0; | 31 const intptr_t kNumInputs = 0; |
| 32 const intptr_t kNumTemps = 0; | 32 const intptr_t kNumTemps = 0; |
| 33 LocationSummary* result = new(zone) LocationSummary( | 33 LocationSummary* result = new (zone) |
| 34 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 34 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 35 result->set_out(0, Location::RegisterLocation(EAX)); | 35 result->set_out(0, Location::RegisterLocation(EAX)); |
| 36 return result; | 36 return result; |
| 37 } | 37 } |
| 38 | 38 |
| 39 | 39 |
| 40 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 40 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
| 41 bool opt) const { | 41 bool opt) const { |
| 42 const intptr_t kNumInputs = 1; | 42 const intptr_t kNumInputs = 1; |
| 43 const intptr_t kNumTemps = 0; | 43 const intptr_t kNumTemps = 0; |
| 44 LocationSummary* locs = new(zone) LocationSummary( | 44 LocationSummary* locs = new (zone) |
| 45 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 45 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 46 locs->set_in(0, Location::AnyOrConstant(value())); | 46 locs->set_in(0, Location::AnyOrConstant(value())); |
| 47 return locs; | 47 return locs; |
| 48 } | 48 } |
| 49 | 49 |
| 50 | 50 |
| 51 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 51 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 52 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 52 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 53 // where PushArgument is handled by BindInstr::EmitNativeCode. | 53 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 54 if (compiler->is_optimizing()) { | 54 if (compiler->is_optimizing()) { |
| 55 Location value = locs()->in(0); | 55 Location value = locs()->in(0); |
| 56 if (value.IsRegister()) { | 56 if (value.IsRegister()) { |
| 57 __ pushl(value.reg()); | 57 __ pushl(value.reg()); |
| 58 } else if (value.IsConstant()) { | 58 } else if (value.IsConstant()) { |
| 59 __ PushObject(value.constant()); | 59 __ PushObject(value.constant()); |
| 60 } else { | 60 } else { |
| 61 ASSERT(value.IsStackSlot()); | 61 ASSERT(value.IsStackSlot()); |
| 62 __ pushl(value.ToStackSlotAddress()); | 62 __ pushl(value.ToStackSlotAddress()); |
| 63 } | 63 } |
| 64 } | 64 } |
| 65 } | 65 } |
| 66 | 66 |
| 67 | 67 |
| 68 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, | 68 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 69 bool opt) const { | |
| 70 const intptr_t kNumInputs = 1; | 69 const intptr_t kNumInputs = 1; |
| 71 const intptr_t kNumTemps = 0; | 70 const intptr_t kNumTemps = 0; |
| 72 LocationSummary* locs = new(zone) LocationSummary( | 71 LocationSummary* locs = new (zone) |
| 73 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 72 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 74 locs->set_in(0, Location::RegisterLocation(EAX)); | 73 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 75 return locs; | 74 return locs; |
| 76 } | 75 } |
| 77 | 76 |
| 78 | 77 |
| 79 // Attempt optimized compilation at return instruction instead of at the entry. | 78 // Attempt optimized compilation at return instruction instead of at the entry. |
| 80 // The entry needs to be patchable, no inlined objects are allowed in the area | 79 // The entry needs to be patchable, no inlined objects are allowed in the area |
| 81 // that will be overwritten by the patch instruction: a jump). | 80 // that will be overwritten by the patch instruction: a jump). |
| 82 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 81 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 83 Register result = locs()->in(0).reg(); | 82 Register result = locs()->in(0).reg(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 104 #endif | 103 #endif |
| 105 __ LeaveFrame(); | 104 __ LeaveFrame(); |
| 106 __ ret(); | 105 __ ret(); |
| 107 } | 106 } |
| 108 | 107 |
| 109 | 108 |
| 110 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 109 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
| 111 bool opt) const { | 110 bool opt) const { |
| 112 const intptr_t kNumInputs = 0; | 111 const intptr_t kNumInputs = 0; |
| 113 const intptr_t stack_index = (local().index() < 0) | 112 const intptr_t stack_index = (local().index() < 0) |
| 114 ? kFirstLocalSlotFromFp - local().index() | 113 ? kFirstLocalSlotFromFp - local().index() |
| 115 : kParamEndSlotFromFp - local().index(); | 114 : kParamEndSlotFromFp - local().index(); |
| 116 return LocationSummary::Make(zone, | 115 return LocationSummary::Make(zone, kNumInputs, |
| 117 kNumInputs, | |
| 118 Location::StackSlot(stack_index), | 116 Location::StackSlot(stack_index), |
| 119 LocationSummary::kNoCall); | 117 LocationSummary::kNoCall); |
| 120 } | 118 } |
| 121 | 119 |
| 122 | 120 |
| 123 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 121 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 124 ASSERT(!compiler->is_optimizing()); | 122 ASSERT(!compiler->is_optimizing()); |
| 125 // Nothing to do. | 123 // Nothing to do. |
| 126 } | 124 } |
| 127 | 125 |
| 128 | 126 |
| 129 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 127 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
| 130 bool opt) const { | 128 bool opt) const { |
| 131 const intptr_t kNumInputs = 1; | 129 const intptr_t kNumInputs = 1; |
| 132 return LocationSummary::Make(zone, | 130 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
| 133 kNumInputs, | |
| 134 Location::SameAsFirstInput(), | |
| 135 LocationSummary::kNoCall); | 131 LocationSummary::kNoCall); |
| 136 } | 132 } |
| 137 | 133 |
| 138 | 134 |
| 139 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 135 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 140 Register value = locs()->in(0).reg(); | 136 Register value = locs()->in(0).reg(); |
| 141 Register result = locs()->out(0).reg(); | 137 Register result = locs()->out(0).reg(); |
| 142 ASSERT(result == value); // Assert that register assignment is correct. | 138 ASSERT(result == value); // Assert that register assignment is correct. |
| 143 __ movl(Address(EBP, local().index() * kWordSize), value); | 139 __ movl(Address(EBP, local().index() * kWordSize), value); |
| 144 } | 140 } |
| 145 | 141 |
| 146 | 142 |
| 147 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 143 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
| 148 bool opt) const { | 144 bool opt) const { |
| 149 const intptr_t kNumInputs = 0; | 145 const intptr_t kNumInputs = 0; |
| 150 return LocationSummary::Make(zone, | 146 return LocationSummary::Make(zone, kNumInputs, |
| 151 kNumInputs, | |
| 152 Assembler::IsSafe(value()) | 147 Assembler::IsSafe(value()) |
| 153 ? Location::Constant(this) | 148 ? Location::Constant(this) |
| 154 : Location::RequiresRegister(), | 149 : Location::RequiresRegister(), |
| 155 LocationSummary::kNoCall); | 150 LocationSummary::kNoCall); |
| 156 } | 151 } |
| 157 | 152 |
| 158 | 153 |
| 159 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 154 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 160 // The register allocator drops constant definitions that have no uses. | 155 // The register allocator drops constant definitions that have no uses. |
| 161 Location out = locs()->out(0); | 156 Location out = locs()->out(0); |
| 162 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); | 157 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); |
| 163 if (out.IsRegister()) { | 158 if (out.IsRegister()) { |
| 164 Register result = out.reg(); | 159 Register result = out.reg(); |
| 165 __ LoadObjectSafely(result, value()); | 160 __ LoadObjectSafely(result, value()); |
| 166 } | 161 } |
| 167 } | 162 } |
| 168 | 163 |
| 169 | 164 |
| 170 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 165 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
| 171 bool opt) const { | 166 bool opt) const { |
| 172 const intptr_t kNumInputs = 0; | 167 const intptr_t kNumInputs = 0; |
| 173 const intptr_t kNumTemps = | 168 const intptr_t kNumTemps = |
| 174 (constant_address() == 0) && (representation() != kUnboxedInt32) ? 1 : 0; | 169 (constant_address() == 0) && (representation() != kUnboxedInt32) ? 1 : 0; |
| 175 LocationSummary* locs = new(zone) LocationSummary( | 170 LocationSummary* locs = new (zone) |
| 176 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 171 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 177 if (representation() == kUnboxedDouble) { | 172 if (representation() == kUnboxedDouble) { |
| 178 locs->set_out(0, Location::RequiresFpuRegister()); | 173 locs->set_out(0, Location::RequiresFpuRegister()); |
| 179 } else { | 174 } else { |
| 180 ASSERT(representation() == kUnboxedInt32); | 175 ASSERT(representation() == kUnboxedInt32); |
| 181 locs->set_out(0, Location::RequiresRegister()); | 176 locs->set_out(0, Location::RequiresRegister()); |
| 182 } | 177 } |
| 183 if (kNumTemps == 1) { | 178 if (kNumTemps == 1) { |
| 184 locs->set_temp(0, Location::RequiresRegister()); | 179 locs->set_temp(0, Location::RequiresRegister()); |
| 185 } | 180 } |
| 186 return locs; | 181 return locs; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 211 UNREACHABLE(); | 206 UNREACHABLE(); |
| 212 } | 207 } |
| 213 } | 208 } |
| 214 } | 209 } |
| 215 | 210 |
| 216 | 211 |
| 217 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 212 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
| 218 bool opt) const { | 213 bool opt) const { |
| 219 const intptr_t kNumInputs = 2; | 214 const intptr_t kNumInputs = 2; |
| 220 const intptr_t kNumTemps = 0; | 215 const intptr_t kNumTemps = 0; |
| 221 LocationSummary* summary = new(zone) LocationSummary( | 216 LocationSummary* summary = new (zone) |
| 222 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 217 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 223 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. | 218 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. |
| 224 summary->set_in(1, Location::RegisterLocation(EDX)); // Type arguments. | 219 summary->set_in(1, Location::RegisterLocation(EDX)); // Type arguments. |
| 225 summary->set_out(0, Location::RegisterLocation(EAX)); | 220 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 226 return summary; | 221 return summary; |
| 227 } | 222 } |
| 228 | 223 |
| 229 | 224 |
| 230 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 225 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
| 231 bool opt) const { | 226 bool opt) const { |
| 232 const intptr_t kNumInputs = 1; | 227 const intptr_t kNumInputs = 1; |
| 233 const intptr_t kNumTemps = 0; | 228 const intptr_t kNumTemps = 0; |
| 234 LocationSummary* locs = new(zone) LocationSummary( | 229 LocationSummary* locs = new (zone) |
| 235 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 230 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 236 locs->set_in(0, Location::RegisterLocation(EAX)); | 231 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 237 locs->set_out(0, Location::RegisterLocation(EAX)); | 232 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 238 return locs; | 233 return locs; |
| 239 } | 234 } |
| 240 | 235 |
| 241 | 236 |
| 242 static void EmitAssertBoolean(Register reg, | 237 static void EmitAssertBoolean(Register reg, |
| 243 TokenPosition token_pos, | 238 TokenPosition token_pos, |
| 244 intptr_t deopt_id, | 239 intptr_t deopt_id, |
| 245 LocationSummary* locs, | 240 LocationSummary* locs, |
| 246 FlowGraphCompiler* compiler) { | 241 FlowGraphCompiler* compiler) { |
| 247 // Check that the type of the value is allowed in conditional context. | 242 // Check that the type of the value is allowed in conditional context. |
| 248 // Call the runtime if the object is not bool::true or bool::false. | 243 // Call the runtime if the object is not bool::true or bool::false. |
| 249 ASSERT(locs->always_calls()); | 244 ASSERT(locs->always_calls()); |
| 250 Label done; | 245 Label done; |
| 251 | 246 |
| 252 if (Isolate::Current()->type_checks()) { | 247 if (Isolate::Current()->type_checks()) { |
| 253 __ CompareObject(reg, Bool::True()); | 248 __ CompareObject(reg, Bool::True()); |
| 254 __ j(EQUAL, &done, Assembler::kNearJump); | 249 __ j(EQUAL, &done, Assembler::kNearJump); |
| 255 __ CompareObject(reg, Bool::False()); | 250 __ CompareObject(reg, Bool::False()); |
| 256 __ j(EQUAL, &done, Assembler::kNearJump); | 251 __ j(EQUAL, &done, Assembler::kNearJump); |
| 257 } else { | 252 } else { |
| 258 ASSERT(Isolate::Current()->asserts()); | 253 ASSERT(Isolate::Current()->asserts()); |
| 259 __ CompareObject(reg, Object::null_instance()); | 254 __ CompareObject(reg, Object::null_instance()); |
| 260 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 255 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 261 } | 256 } |
| 262 | 257 |
| 263 __ pushl(reg); // Push the source object. | 258 __ pushl(reg); // Push the source object. |
| 264 compiler->GenerateRuntimeCall(token_pos, | 259 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
| 265 deopt_id, | 260 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
| 266 kNonBoolTypeErrorRuntimeEntry, | |
| 267 1, | |
| 268 locs); | |
| 269 // We should never return here. | 261 // We should never return here. |
| 270 __ int3(); | 262 __ int3(); |
| 271 __ Bind(&done); | 263 __ Bind(&done); |
| 272 } | 264 } |
| 273 | 265 |
| 274 | 266 |
| 275 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 267 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 276 Register obj = locs()->in(0).reg(); | 268 Register obj = locs()->in(0).reg(); |
| 277 Register result = locs()->out(0).reg(); | 269 Register result = locs()->out(0).reg(); |
| 278 | 270 |
| 279 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 271 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 280 ASSERT(obj == result); | 272 ASSERT(obj == result); |
| 281 } | 273 } |
| 282 | 274 |
| 283 | 275 |
| 284 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 276 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 285 switch (kind) { | 277 switch (kind) { |
| 286 case Token::kEQ: return EQUAL; | 278 case Token::kEQ: |
| 287 case Token::kNE: return NOT_EQUAL; | 279 return EQUAL; |
| 288 case Token::kLT: return LESS; | 280 case Token::kNE: |
| 289 case Token::kGT: return GREATER; | 281 return NOT_EQUAL; |
| 290 case Token::kLTE: return LESS_EQUAL; | 282 case Token::kLT: |
| 291 case Token::kGTE: return GREATER_EQUAL; | 283 return LESS; |
| 284 case Token::kGT: |
| 285 return GREATER; |
| 286 case Token::kLTE: |
| 287 return LESS_EQUAL; |
| 288 case Token::kGTE: |
| 289 return GREATER_EQUAL; |
| 292 default: | 290 default: |
| 293 UNREACHABLE(); | 291 UNREACHABLE(); |
| 294 return OVERFLOW; | 292 return OVERFLOW; |
| 295 } | 293 } |
| 296 } | 294 } |
| 297 | 295 |
| 298 | 296 |
| 299 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 297 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
| 300 bool opt) const { | 298 bool opt) const { |
| 301 const intptr_t kNumInputs = 2; | 299 const intptr_t kNumInputs = 2; |
| 302 if (operation_cid() == kMintCid) { | 300 if (operation_cid() == kMintCid) { |
| 303 const intptr_t kNumTemps = 0; | 301 const intptr_t kNumTemps = 0; |
| 304 LocationSummary* locs = new(zone) LocationSummary( | 302 LocationSummary* locs = new (zone) |
| 305 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 303 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 306 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 304 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 307 Location::RequiresRegister())); | 305 Location::RequiresRegister())); |
| 308 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 306 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 309 Location::RequiresRegister())); | 307 Location::RequiresRegister())); |
| 310 locs->set_out(0, Location::RequiresRegister()); | 308 locs->set_out(0, Location::RequiresRegister()); |
| 311 return locs; | 309 return locs; |
| 312 } | 310 } |
| 313 if (operation_cid() == kDoubleCid) { | 311 if (operation_cid() == kDoubleCid) { |
| 314 const intptr_t kNumTemps = 0; | 312 const intptr_t kNumTemps = 0; |
| 315 LocationSummary* locs = new(zone) LocationSummary( | 313 LocationSummary* locs = new (zone) |
| 316 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 314 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 317 locs->set_in(0, Location::RequiresFpuRegister()); | 315 locs->set_in(0, Location::RequiresFpuRegister()); |
| 318 locs->set_in(1, Location::RequiresFpuRegister()); | 316 locs->set_in(1, Location::RequiresFpuRegister()); |
| 319 locs->set_out(0, Location::RequiresRegister()); | 317 locs->set_out(0, Location::RequiresRegister()); |
| 320 return locs; | 318 return locs; |
| 321 } | 319 } |
| 322 if (operation_cid() == kSmiCid) { | 320 if (operation_cid() == kSmiCid) { |
| 323 const intptr_t kNumTemps = 0; | 321 const intptr_t kNumTemps = 0; |
| 324 LocationSummary* locs = new(zone) LocationSummary( | 322 LocationSummary* locs = new (zone) |
| 325 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 323 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 326 locs->set_in(0, Location::RegisterOrConstant(left())); | 324 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 327 // Only one input can be a constant operand. The case of two constant | 325 // Only one input can be a constant operand. The case of two constant |
| 328 // operands should be handled by constant propagation. | 326 // operands should be handled by constant propagation. |
| 329 // Only right can be a stack slot. | 327 // Only right can be a stack slot. |
| 330 locs->set_in(1, locs->in(0).IsConstant() | 328 locs->set_in(1, locs->in(0).IsConstant() |
| 331 ? Location::RequiresRegister() | 329 ? Location::RequiresRegister() |
| 332 : Location::RegisterOrConstant(right())); | 330 : Location::RegisterOrConstant(right())); |
| 333 locs->set_out(0, Location::RequiresRegister()); | 331 locs->set_out(0, Location::RequiresRegister()); |
| 334 return locs; | 332 return locs; |
| 335 } | 333 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 352 } else { | 350 } else { |
| 353 __ j(ZERO, value_is_smi); | 351 __ j(ZERO, value_is_smi); |
| 354 } | 352 } |
| 355 __ LoadClassId(value_cid_reg, value_reg); | 353 __ LoadClassId(value_cid_reg, value_reg); |
| 356 __ Bind(&done); | 354 __ Bind(&done); |
| 357 } | 355 } |
| 358 | 356 |
| 359 | 357 |
| 360 static Condition FlipCondition(Condition condition) { | 358 static Condition FlipCondition(Condition condition) { |
| 361 switch (condition) { | 359 switch (condition) { |
| 362 case EQUAL: return EQUAL; | 360 case EQUAL: |
| 363 case NOT_EQUAL: return NOT_EQUAL; | 361 return EQUAL; |
| 364 case LESS: return GREATER; | 362 case NOT_EQUAL: |
| 365 case LESS_EQUAL: return GREATER_EQUAL; | 363 return NOT_EQUAL; |
| 366 case GREATER: return LESS; | 364 case LESS: |
| 367 case GREATER_EQUAL: return LESS_EQUAL; | 365 return GREATER; |
| 368 case BELOW: return ABOVE; | 366 case LESS_EQUAL: |
| 369 case BELOW_EQUAL: return ABOVE_EQUAL; | 367 return GREATER_EQUAL; |
| 370 case ABOVE: return BELOW; | 368 case GREATER: |
| 371 case ABOVE_EQUAL: return BELOW_EQUAL; | 369 return LESS; |
| 370 case GREATER_EQUAL: |
| 371 return LESS_EQUAL; |
| 372 case BELOW: |
| 373 return ABOVE; |
| 374 case BELOW_EQUAL: |
| 375 return ABOVE_EQUAL; |
| 376 case ABOVE: |
| 377 return BELOW; |
| 378 case ABOVE_EQUAL: |
| 379 return BELOW_EQUAL; |
| 372 default: | 380 default: |
| 373 UNIMPLEMENTED(); | 381 UNIMPLEMENTED(); |
| 374 return EQUAL; | 382 return EQUAL; |
| 375 } | 383 } |
| 376 } | 384 } |
| 377 | 385 |
| 378 | 386 |
| 379 static Condition NegateCondition(Condition condition) { | 387 static Condition NegateCondition(Condition condition) { |
| 380 switch (condition) { | 388 switch (condition) { |
| 381 case EQUAL: return NOT_EQUAL; | 389 case EQUAL: |
| 382 case NOT_EQUAL: return EQUAL; | 390 return NOT_EQUAL; |
| 383 case LESS: return GREATER_EQUAL; | 391 case NOT_EQUAL: |
| 384 case LESS_EQUAL: return GREATER; | 392 return EQUAL; |
| 385 case GREATER: return LESS_EQUAL; | 393 case LESS: |
| 386 case GREATER_EQUAL: return LESS; | 394 return GREATER_EQUAL; |
| 387 case BELOW: return ABOVE_EQUAL; | 395 case LESS_EQUAL: |
| 388 case BELOW_EQUAL: return ABOVE; | 396 return GREATER; |
| 389 case ABOVE: return BELOW_EQUAL; | 397 case GREATER: |
| 390 case ABOVE_EQUAL: return BELOW; | 398 return LESS_EQUAL; |
| 391 case PARITY_ODD: return PARITY_EVEN; | 399 case GREATER_EQUAL: |
| 392 case PARITY_EVEN: return PARITY_ODD; | 400 return LESS; |
| 401 case BELOW: |
| 402 return ABOVE_EQUAL; |
| 403 case BELOW_EQUAL: |
| 404 return ABOVE; |
| 405 case ABOVE: |
| 406 return BELOW_EQUAL; |
| 407 case ABOVE_EQUAL: |
| 408 return BELOW; |
| 409 case PARITY_ODD: |
| 410 return PARITY_EVEN; |
| 411 case PARITY_EVEN: |
| 412 return PARITY_ODD; |
| 393 default: | 413 default: |
| 394 UNIMPLEMENTED(); | 414 UNIMPLEMENTED(); |
| 395 return EQUAL; | 415 return EQUAL; |
| 396 } | 416 } |
| 397 } | 417 } |
| 398 | 418 |
| 399 | 419 |
| 400 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 420 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 401 Condition true_condition, | 421 Condition true_condition, |
| 402 BranchLabels labels) { | 422 BranchLabels labels) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 __ cmpl(left.reg(), right.ToStackSlotAddress()); | 455 __ cmpl(left.reg(), right.ToStackSlotAddress()); |
| 436 } else { | 456 } else { |
| 437 __ cmpl(left.reg(), right.reg()); | 457 __ cmpl(left.reg(), right.reg()); |
| 438 } | 458 } |
| 439 return true_condition; | 459 return true_condition; |
| 440 } | 460 } |
| 441 | 461 |
| 442 | 462 |
| 443 static Condition TokenKindToMintCondition(Token::Kind kind) { | 463 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 444 switch (kind) { | 464 switch (kind) { |
| 445 case Token::kEQ: return EQUAL; | 465 case Token::kEQ: |
| 446 case Token::kNE: return NOT_EQUAL; | 466 return EQUAL; |
| 447 case Token::kLT: return LESS; | 467 case Token::kNE: |
| 448 case Token::kGT: return GREATER; | 468 return NOT_EQUAL; |
| 449 case Token::kLTE: return LESS_EQUAL; | 469 case Token::kLT: |
| 450 case Token::kGTE: return GREATER_EQUAL; | 470 return LESS; |
| 471 case Token::kGT: |
| 472 return GREATER; |
| 473 case Token::kLTE: |
| 474 return LESS_EQUAL; |
| 475 case Token::kGTE: |
| 476 return GREATER_EQUAL; |
| 451 default: | 477 default: |
| 452 UNREACHABLE(); | 478 UNREACHABLE(); |
| 453 return OVERFLOW; | 479 return OVERFLOW; |
| 454 } | 480 } |
| 455 } | 481 } |
| 456 | 482 |
| 457 | 483 |
| 458 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 484 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 459 const LocationSummary& locs, | 485 const LocationSummary& locs, |
| 460 Token::Kind kind, | 486 Token::Kind kind, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 __ j(FlipCondition(hi_cond), labels.false_label); | 543 __ j(FlipCondition(hi_cond), labels.false_label); |
| 518 | 544 |
| 519 // If upper is equal, compare lower half. | 545 // If upper is equal, compare lower half. |
| 520 __ cmpl(left1, right1); | 546 __ cmpl(left1, right1); |
| 521 return lo_cond; | 547 return lo_cond; |
| 522 } | 548 } |
| 523 | 549 |
| 524 | 550 |
| 525 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 551 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 526 switch (kind) { | 552 switch (kind) { |
| 527 case Token::kEQ: return EQUAL; | 553 case Token::kEQ: |
| 528 case Token::kNE: return NOT_EQUAL; | 554 return EQUAL; |
| 529 case Token::kLT: return BELOW; | 555 case Token::kNE: |
| 530 case Token::kGT: return ABOVE; | 556 return NOT_EQUAL; |
| 531 case Token::kLTE: return BELOW_EQUAL; | 557 case Token::kLT: |
| 532 case Token::kGTE: return ABOVE_EQUAL; | 558 return BELOW; |
| 559 case Token::kGT: |
| 560 return ABOVE; |
| 561 case Token::kLTE: |
| 562 return BELOW_EQUAL; |
| 563 case Token::kGTE: |
| 564 return ABOVE_EQUAL; |
| 533 default: | 565 default: |
| 534 UNREACHABLE(); | 566 UNREACHABLE(); |
| 535 return OVERFLOW; | 567 return OVERFLOW; |
| 536 } | 568 } |
| 537 } | 569 } |
| 538 | 570 |
| 539 | 571 |
| 540 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 572 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 541 const LocationSummary& locs, | 573 const LocationSummary& locs, |
| 542 Token::Kind kind, | 574 Token::Kind kind, |
| 543 BranchLabels labels) { | 575 BranchLabels labels) { |
| 544 XmmRegister left = locs.in(0).fpu_reg(); | 576 XmmRegister left = locs.in(0).fpu_reg(); |
| 545 XmmRegister right = locs.in(1).fpu_reg(); | 577 XmmRegister right = locs.in(1).fpu_reg(); |
| 546 | 578 |
| 547 __ comisd(left, right); | 579 __ comisd(left, right); |
| 548 | 580 |
| 549 Condition true_condition = TokenKindToDoubleCondition(kind); | 581 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 550 Label* nan_result = (true_condition == NOT_EQUAL) | 582 Label* nan_result = |
| 551 ? labels.true_label : labels.false_label; | 583 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; |
| 552 __ j(PARITY_EVEN, nan_result); | 584 __ j(PARITY_EVEN, nan_result); |
| 553 return true_condition; | 585 return true_condition; |
| 554 } | 586 } |
| 555 | 587 |
| 556 | 588 |
| 557 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 589 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 558 BranchLabels labels) { | 590 BranchLabels labels) { |
| 559 if (operation_cid() == kSmiCid) { | 591 if (operation_cid() == kSmiCid) { |
| 560 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 592 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 561 } else if (operation_cid() == kMintCid) { | 593 } else if (operation_cid() == kMintCid) { |
| 562 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels); | 594 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels); |
| 563 } else { | 595 } else { |
| 564 ASSERT(operation_cid() == kDoubleCid); | 596 ASSERT(operation_cid() == kDoubleCid); |
| 565 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 597 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 566 } | 598 } |
| 567 } | 599 } |
| 568 | 600 |
| 569 | 601 |
| 570 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 602 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 571 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 603 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 572 | 604 |
| 573 Label is_true, is_false; | 605 Label is_true, is_false; |
| 574 BranchLabels labels = { &is_true, &is_false, &is_false }; | 606 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 575 Condition true_condition = EmitComparisonCode(compiler, labels); | 607 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 576 EmitBranchOnCondition(compiler, true_condition, labels); | 608 EmitBranchOnCondition(compiler, true_condition, labels); |
| 577 | 609 |
| 578 Register result = locs()->out(0).reg(); | 610 Register result = locs()->out(0).reg(); |
| 579 Label done; | 611 Label done; |
| 580 __ Bind(&is_false); | 612 __ Bind(&is_false); |
| 581 __ LoadObject(result, Bool::False()); | 613 __ LoadObject(result, Bool::False()); |
| 582 __ jmp(&done, Assembler::kNearJump); | 614 __ jmp(&done, Assembler::kNearJump); |
| 583 __ Bind(&is_true); | 615 __ Bind(&is_true); |
| 584 __ LoadObject(result, Bool::True()); | 616 __ LoadObject(result, Bool::True()); |
| 585 __ Bind(&done); | 617 __ Bind(&done); |
| 586 } | 618 } |
| 587 | 619 |
| 588 | 620 |
| 589 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 621 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 590 BranchInstr* branch) { | 622 BranchInstr* branch) { |
| 591 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 623 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 592 | 624 |
| 593 BranchLabels labels = compiler->CreateBranchLabels(branch); | 625 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 594 Condition true_condition = EmitComparisonCode(compiler, labels); | 626 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 595 EmitBranchOnCondition(compiler, true_condition, labels); | 627 EmitBranchOnCondition(compiler, true_condition, labels); |
| 596 } | 628 } |
| 597 | 629 |
| 598 | 630 |
| 599 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, | 631 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 600 bool opt) const { | |
| 601 const intptr_t kNumInputs = 2; | 632 const intptr_t kNumInputs = 2; |
| 602 const intptr_t kNumTemps = 0; | 633 const intptr_t kNumTemps = 0; |
| 603 LocationSummary* locs = new(zone) LocationSummary( | 634 LocationSummary* locs = new (zone) |
| 604 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 635 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 605 locs->set_in(0, Location::RequiresRegister()); | 636 locs->set_in(0, Location::RequiresRegister()); |
| 606 // Only one input can be a constant operand. The case of two constant | 637 // Only one input can be a constant operand. The case of two constant |
| 607 // operands should be handled by constant propagation. | 638 // operands should be handled by constant propagation. |
| 608 locs->set_in(1, Location::RegisterOrConstant(right())); | 639 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 609 return locs; | 640 return locs; |
| 610 } | 641 } |
| 611 | 642 |
| 612 | 643 |
| 613 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 644 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 614 BranchLabels labels) { | 645 BranchLabels labels) { |
| 615 Register left = locs()->in(0).reg(); | 646 Register left = locs()->in(0).reg(); |
| 616 Location right = locs()->in(1); | 647 Location right = locs()->in(1); |
| 617 if (right.IsConstant()) { | 648 if (right.IsConstant()) { |
| 618 ASSERT(right.constant().IsSmi()); | 649 ASSERT(right.constant().IsSmi()); |
| 619 const int32_t imm = | 650 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); |
| 620 reinterpret_cast<int32_t>(right.constant().raw()); | |
| 621 __ testl(left, Immediate(imm)); | 651 __ testl(left, Immediate(imm)); |
| 622 } else { | 652 } else { |
| 623 __ testl(left, right.reg()); | 653 __ testl(left, right.reg()); |
| 624 } | 654 } |
| 625 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 655 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
| 626 return true_condition; | 656 return true_condition; |
| 627 } | 657 } |
| 628 | 658 |
| 629 | 659 |
| 630 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 660 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 631 // Never emitted outside of the BranchInstr. | 661 // Never emitted outside of the BranchInstr. |
| 632 UNREACHABLE(); | 662 UNREACHABLE(); |
| 633 } | 663 } |
| 634 | 664 |
| 635 | 665 |
| 636 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 666 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 637 BranchInstr* branch) { | 667 BranchInstr* branch) { |
| 638 BranchLabels labels = compiler->CreateBranchLabels(branch); | 668 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 639 Condition true_condition = EmitComparisonCode(compiler, labels); | 669 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 640 EmitBranchOnCondition(compiler, true_condition, labels); | 670 EmitBranchOnCondition(compiler, true_condition, labels); |
| 641 } | 671 } |
| 642 | 672 |
| 643 | 673 |
| 644 | |
| 645 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 674 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
| 646 bool opt) const { | 675 bool opt) const { |
| 647 const intptr_t kNumInputs = 1; | 676 const intptr_t kNumInputs = 1; |
| 648 const intptr_t kNumTemps = 1; | 677 const intptr_t kNumTemps = 1; |
| 649 LocationSummary* locs = new(zone) LocationSummary( | 678 LocationSummary* locs = new (zone) |
| 650 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 679 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 651 locs->set_in(0, Location::RequiresRegister()); | 680 locs->set_in(0, Location::RequiresRegister()); |
| 652 locs->set_temp(0, Location::RequiresRegister()); | 681 locs->set_temp(0, Location::RequiresRegister()); |
| 653 locs->set_out(0, Location::RequiresRegister()); | 682 locs->set_out(0, Location::RequiresRegister()); |
| 654 return locs; | 683 return locs; |
| 655 } | 684 } |
| 656 | 685 |
| 657 | 686 |
| 658 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 687 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 659 BranchLabels labels) { | 688 BranchLabels labels) { |
| 660 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 689 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
| 661 Register val_reg = locs()->in(0).reg(); | 690 Register val_reg = locs()->in(0).reg(); |
| 662 Register cid_reg = locs()->temp(0).reg(); | 691 Register cid_reg = locs()->temp(0).reg(); |
| 663 | 692 |
| 664 Label* deopt = CanDeoptimize() | 693 Label* deopt = |
| 665 ? compiler->AddDeoptStub(deopt_id(), | 694 CanDeoptimize() |
| 666 ICData::kDeoptTestCids, | 695 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, |
| 667 licm_hoisted_ ? ICData::kHoisted : 0) | 696 licm_hoisted_ ? ICData::kHoisted : 0) |
| 668 : NULL; | 697 : NULL; |
| 669 | 698 |
| 670 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 699 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
| 671 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 700 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
| 672 ASSERT(data[0] == kSmiCid); | 701 ASSERT(data[0] == kSmiCid); |
| 673 bool result = data[1] == true_result; | 702 bool result = data[1] == true_result; |
| 674 __ testl(val_reg, Immediate(kSmiTagMask)); | 703 __ testl(val_reg, Immediate(kSmiTagMask)); |
| 675 __ j(ZERO, result ? labels.true_label : labels.false_label); | 704 __ j(ZERO, result ? labels.true_label : labels.false_label); |
| 676 __ LoadClassId(cid_reg, val_reg); | 705 __ LoadClassId(cid_reg, val_reg); |
| 677 for (intptr_t i = 2; i < data.length(); i += 2) { | 706 for (intptr_t i = 2; i < data.length(); i += 2) { |
| 678 const intptr_t test_cid = data[i]; | 707 const intptr_t test_cid = data[i]; |
| 679 ASSERT(test_cid != kSmiCid); | 708 ASSERT(test_cid != kSmiCid); |
| 680 result = data[i + 1] == true_result; | 709 result = data[i + 1] == true_result; |
| 681 __ cmpl(cid_reg, Immediate(test_cid)); | 710 __ cmpl(cid_reg, Immediate(test_cid)); |
| 682 __ j(EQUAL, result ? labels.true_label : labels.false_label); | 711 __ j(EQUAL, result ? labels.true_label : labels.false_label); |
| 683 } | 712 } |
| 684 // No match found, deoptimize or false. | 713 // No match found, deoptimize or false. |
| 685 if (deopt == NULL) { | 714 if (deopt == NULL) { |
| 686 Label* target = result ? labels.false_label : labels.true_label; | 715 Label* target = result ? labels.false_label : labels.true_label; |
| 687 if (target != labels.fall_through) { | 716 if (target != labels.fall_through) { |
| 688 __ jmp(target); | 717 __ jmp(target); |
| 689 } | 718 } |
| 690 } else { | 719 } else { |
| 691 __ jmp(deopt); | 720 __ jmp(deopt); |
| 692 } | 721 } |
| 693 // Dummy result as the last instruction is a jump, any conditional | 722 // Dummy result as the last instruction is a jump, any conditional |
| 694 // branch using the result will therefore be skipped. | 723 // branch using the result will therefore be skipped. |
| 695 return ZERO; | 724 return ZERO; |
| 696 } | 725 } |
| 697 | 726 |
| 698 | 727 |
| 699 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 728 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 700 BranchInstr* branch) { | 729 BranchInstr* branch) { |
| 701 BranchLabels labels = compiler->CreateBranchLabels(branch); | 730 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 702 EmitComparisonCode(compiler, labels); | 731 EmitComparisonCode(compiler, labels); |
| 703 } | 732 } |
| 704 | 733 |
| 705 | 734 |
| 706 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 735 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 707 Register result_reg = locs()->out(0).reg(); | 736 Register result_reg = locs()->out(0).reg(); |
| 708 Label is_true, is_false, done; | 737 Label is_true, is_false, done; |
| 709 BranchLabels labels = { &is_true, &is_false, &is_false }; | 738 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 710 EmitComparisonCode(compiler, labels); | 739 EmitComparisonCode(compiler, labels); |
| 711 __ Bind(&is_false); | 740 __ Bind(&is_false); |
| 712 __ LoadObject(result_reg, Bool::False()); | 741 __ LoadObject(result_reg, Bool::False()); |
| 713 __ jmp(&done, Assembler::kNearJump); | 742 __ jmp(&done, Assembler::kNearJump); |
| 714 __ Bind(&is_true); | 743 __ Bind(&is_true); |
| 715 __ LoadObject(result_reg, Bool::True()); | 744 __ LoadObject(result_reg, Bool::True()); |
| 716 __ Bind(&done); | 745 __ Bind(&done); |
| 717 } | 746 } |
| 718 | 747 |
| 719 | 748 |
| 720 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 749 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
| 721 bool opt) const { | 750 bool opt) const { |
| 722 const intptr_t kNumInputs = 2; | 751 const intptr_t kNumInputs = 2; |
| 723 const intptr_t kNumTemps = 0; | 752 const intptr_t kNumTemps = 0; |
| 724 if (operation_cid() == kMintCid) { | 753 if (operation_cid() == kMintCid) { |
| 725 const intptr_t kNumTemps = 0; | 754 const intptr_t kNumTemps = 0; |
| 726 LocationSummary* locs = new(zone) LocationSummary( | 755 LocationSummary* locs = new (zone) |
| 727 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 756 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 728 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 757 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 729 Location::RequiresRegister())); | 758 Location::RequiresRegister())); |
| 730 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 759 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 731 Location::RequiresRegister())); | 760 Location::RequiresRegister())); |
| 732 locs->set_out(0, Location::RequiresRegister()); | 761 locs->set_out(0, Location::RequiresRegister()); |
| 733 return locs; | 762 return locs; |
| 734 } | 763 } |
| 735 if (operation_cid() == kDoubleCid) { | 764 if (operation_cid() == kDoubleCid) { |
| 736 LocationSummary* summary = new(zone) LocationSummary( | 765 LocationSummary* summary = new (zone) |
| 737 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 766 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 738 summary->set_in(0, Location::RequiresFpuRegister()); | 767 summary->set_in(0, Location::RequiresFpuRegister()); |
| 739 summary->set_in(1, Location::RequiresFpuRegister()); | 768 summary->set_in(1, Location::RequiresFpuRegister()); |
| 740 summary->set_out(0, Location::RequiresRegister()); | 769 summary->set_out(0, Location::RequiresRegister()); |
| 741 return summary; | 770 return summary; |
| 742 } | 771 } |
| 743 ASSERT(operation_cid() == kSmiCid); | 772 ASSERT(operation_cid() == kSmiCid); |
| 744 LocationSummary* summary = new(zone) LocationSummary( | 773 LocationSummary* summary = new (zone) |
| 745 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 774 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 746 summary->set_in(0, Location::RegisterOrConstant(left())); | 775 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 747 // Only one input can be a constant operand. The case of two constant | 776 // Only one input can be a constant operand. The case of two constant |
| 748 // operands should be handled by constant propagation. | 777 // operands should be handled by constant propagation. |
| 749 summary->set_in(1, summary->in(0).IsConstant() | 778 summary->set_in(1, summary->in(0).IsConstant() |
| 750 ? Location::RequiresRegister() | 779 ? Location::RequiresRegister() |
| 751 : Location::RegisterOrConstant(right())); | 780 : Location::RegisterOrConstant(right())); |
| 752 summary->set_out(0, Location::RequiresRegister()); | 781 summary->set_out(0, Location::RequiresRegister()); |
| 753 return summary; | 782 return summary; |
| 754 } | 783 } |
| 755 | 784 |
| 756 | 785 |
| 757 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 786 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 758 BranchLabels labels) { | 787 BranchLabels labels) { |
| 759 if (operation_cid() == kSmiCid) { | 788 if (operation_cid() == kSmiCid) { |
| 760 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 789 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 761 } else if (operation_cid() == kMintCid) { | 790 } else if (operation_cid() == kMintCid) { |
| 762 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); | 791 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); |
| 763 } else { | 792 } else { |
| 764 ASSERT(operation_cid() == kDoubleCid); | 793 ASSERT(operation_cid() == kDoubleCid); |
| 765 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 794 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 766 } | 795 } |
| 767 } | 796 } |
| 768 | 797 |
| 769 | 798 |
| 770 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 799 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 771 Label is_true, is_false; | 800 Label is_true, is_false; |
| 772 BranchLabels labels = { &is_true, &is_false, &is_false }; | 801 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 773 Condition true_condition = EmitComparisonCode(compiler, labels); | 802 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 774 EmitBranchOnCondition(compiler, true_condition, labels); | 803 EmitBranchOnCondition(compiler, true_condition, labels); |
| 775 | 804 |
| 776 Register result = locs()->out(0).reg(); | 805 Register result = locs()->out(0).reg(); |
| 777 Label done; | 806 Label done; |
| 778 __ Bind(&is_false); | 807 __ Bind(&is_false); |
| 779 __ LoadObject(result, Bool::False()); | 808 __ LoadObject(result, Bool::False()); |
| 780 __ jmp(&done, Assembler::kNearJump); | 809 __ jmp(&done, Assembler::kNearJump); |
| 781 __ Bind(&is_true); | 810 __ Bind(&is_true); |
| 782 __ LoadObject(result, Bool::True()); | 811 __ LoadObject(result, Bool::True()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 800 | 829 |
| 801 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 830 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 802 SetupNative(); | 831 SetupNative(); |
| 803 Register result = locs()->out(0).reg(); | 832 Register result = locs()->out(0).reg(); |
| 804 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 833 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
| 805 | 834 |
| 806 // Push the result place holder initialized to NULL. | 835 // Push the result place holder initialized to NULL. |
| 807 __ PushObject(Object::null_object()); | 836 __ PushObject(Object::null_object()); |
| 808 // Pass a pointer to the first argument in EAX. | 837 // Pass a pointer to the first argument in EAX. |
| 809 if (!function().HasOptionalParameters()) { | 838 if (!function().HasOptionalParameters()) { |
| 810 __ leal(EAX, Address(EBP, (kParamEndSlotFromFp + | 839 __ leal(EAX, |
| 811 function().NumParameters()) * kWordSize)); | 840 Address(EBP, (kParamEndSlotFromFp + function().NumParameters()) * |
| 841 kWordSize)); |
| 812 } else { | 842 } else { |
| 813 __ leal(EAX, Address(EBP, kFirstLocalSlotFromFp * kWordSize)); | 843 __ leal(EAX, Address(EBP, kFirstLocalSlotFromFp * kWordSize)); |
| 814 } | 844 } |
| 815 __ movl(EDX, Immediate(argc_tag)); | 845 __ movl(EDX, Immediate(argc_tag)); |
| 816 | 846 |
| 817 const StubEntry* stub_entry; | 847 const StubEntry* stub_entry; |
| 818 if (link_lazily()) { | 848 if (link_lazily()) { |
| 819 stub_entry = StubCode::CallBootstrapCFunction_entry(); | 849 stub_entry = StubCode::CallBootstrapCFunction_entry(); |
| 820 __ movl(ECX, Immediate(NativeEntry::LinkNativeCallEntry())); | 850 __ movl(ECX, Immediate(NativeEntry::LinkNativeCallEntry())); |
| 821 } else { | 851 } else { |
| 822 stub_entry = (is_bootstrap_native()) ? | 852 stub_entry = (is_bootstrap_native()) |
| 823 StubCode::CallBootstrapCFunction_entry() : | 853 ? StubCode::CallBootstrapCFunction_entry() |
| 824 StubCode::CallNativeCFunction_entry(); | 854 : StubCode::CallNativeCFunction_entry(); |
| 825 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); | 855 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); |
| 826 __ movl(ECX, Immediate(label.address())); | 856 __ movl(ECX, Immediate(label.address())); |
| 827 } | 857 } |
| 828 compiler->GenerateCall(token_pos(), | 858 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
| 829 *stub_entry, | |
| 830 RawPcDescriptors::kOther, | |
| 831 locs()); | 859 locs()); |
| 832 __ popl(result); | 860 __ popl(result); |
| 833 } | 861 } |
| 834 | 862 |
| 835 | 863 |
| 836 static bool CanBeImmediateIndex(Value* value, intptr_t cid) { | 864 static bool CanBeImmediateIndex(Value* value, intptr_t cid) { |
| 837 ConstantInstr* constant = value->definition()->AsConstant(); | 865 ConstantInstr* constant = value->definition()->AsConstant(); |
| 838 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { | 866 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { |
| 839 return false; | 867 return false; |
| 840 } | 868 } |
| 841 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | 869 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |
| 842 const intptr_t scale = Instance::ElementSizeFor(cid); | 870 const intptr_t scale = Instance::ElementSizeFor(cid); |
| 843 const intptr_t offset = Instance::DataOffsetFor(cid); | 871 const intptr_t offset = Instance::DataOffsetFor(cid); |
| 844 const int64_t displacement = index * scale + offset; | 872 const int64_t displacement = index * scale + offset; |
| 845 return Utils::IsInt(32, displacement); | 873 return Utils::IsInt(32, displacement); |
| 846 } | 874 } |
| 847 | 875 |
| 848 | 876 |
| 849 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 877 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
| 850 Zone* zone, bool opt) const { | 878 Zone* zone, |
| 879 bool opt) const { |
| 851 const intptr_t kNumInputs = 1; | 880 const intptr_t kNumInputs = 1; |
| 852 // TODO(fschneider): Allow immediate operands for the char code. | 881 // TODO(fschneider): Allow immediate operands for the char code. |
| 853 return LocationSummary::Make(zone, | 882 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 854 kNumInputs, | |
| 855 Location::RequiresRegister(), | |
| 856 LocationSummary::kNoCall); | 883 LocationSummary::kNoCall); |
| 857 } | 884 } |
| 858 | 885 |
| 859 | 886 |
| 860 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 887 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
| 861 FlowGraphCompiler* compiler) { | 888 FlowGraphCompiler* compiler) { |
| 862 Register char_code = locs()->in(0).reg(); | 889 Register char_code = locs()->in(0).reg(); |
| 863 Register result = locs()->out(0).reg(); | 890 Register result = locs()->out(0).reg(); |
| 864 __ movl(result, | 891 __ movl(result, |
| 865 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); | 892 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); |
| 866 __ movl(result, Address(result, | 893 __ movl(result, Address(result, char_code, |
| 867 char_code, | |
| 868 TIMES_HALF_WORD_SIZE, // Char code is a smi. | 894 TIMES_HALF_WORD_SIZE, // Char code is a smi. |
| 869 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 895 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
| 870 } | 896 } |
| 871 | 897 |
| 872 | 898 |
| 873 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 899 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
| 874 bool opt) const { | 900 bool opt) const { |
| 875 const intptr_t kNumInputs = 1; | 901 const intptr_t kNumInputs = 1; |
| 876 return LocationSummary::Make(zone, | 902 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 877 kNumInputs, | |
| 878 Location::RequiresRegister(), | |
| 879 LocationSummary::kNoCall); | 903 LocationSummary::kNoCall); |
| 880 } | 904 } |
| 881 | 905 |
| 882 | 906 |
| 883 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 907 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 884 ASSERT(cid_ == kOneByteStringCid); | 908 ASSERT(cid_ == kOneByteStringCid); |
| 885 Register str = locs()->in(0).reg(); | 909 Register str = locs()->in(0).reg(); |
| 886 Register result = locs()->out(0).reg(); | 910 Register result = locs()->out(0).reg(); |
| 887 Label is_one, done; | 911 Label is_one, done; |
| 888 __ movl(result, FieldAddress(str, String::length_offset())); | 912 __ movl(result, FieldAddress(str, String::length_offset())); |
| 889 __ cmpl(result, Immediate(Smi::RawValue(1))); | 913 __ cmpl(result, Immediate(Smi::RawValue(1))); |
| 890 __ j(EQUAL, &is_one, Assembler::kNearJump); | 914 __ j(EQUAL, &is_one, Assembler::kNearJump); |
| 891 __ movl(result, Immediate(Smi::RawValue(-1))); | 915 __ movl(result, Immediate(Smi::RawValue(-1))); |
| 892 __ jmp(&done); | 916 __ jmp(&done); |
| 893 __ Bind(&is_one); | 917 __ Bind(&is_one); |
| 894 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); | 918 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); |
| 895 __ SmiTag(result); | 919 __ SmiTag(result); |
| 896 __ Bind(&done); | 920 __ Bind(&done); |
| 897 } | 921 } |
| 898 | 922 |
| 899 | 923 |
| 900 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 924 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
| 901 bool opt) const { | 925 bool opt) const { |
| 902 const intptr_t kNumInputs = 1; | 926 const intptr_t kNumInputs = 1; |
| 903 const intptr_t kNumTemps = 0; | 927 const intptr_t kNumTemps = 0; |
| 904 LocationSummary* summary = new(zone) LocationSummary( | 928 LocationSummary* summary = new (zone) |
| 905 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 929 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 906 summary->set_in(0, Location::RegisterLocation(EAX)); | 930 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 907 summary->set_out(0, Location::RegisterLocation(EAX)); | 931 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 908 return summary; | 932 return summary; |
| 909 } | 933 } |
| 910 | 934 |
| 911 | 935 |
| 912 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 936 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 913 Register array = locs()->in(0).reg(); | 937 Register array = locs()->in(0).reg(); |
| 914 __ pushl(array); | 938 __ pushl(array); |
| 915 const int kNumberOfArguments = 1; | 939 const int kNumberOfArguments = 1; |
| 916 const Array& kNoArgumentNames = Object::null_array(); | 940 const Array& kNoArgumentNames = Object::null_array(); |
| 917 compiler->GenerateStaticCall(deopt_id(), | 941 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
| 918 token_pos(), | 942 kNumberOfArguments, kNoArgumentNames, locs(), |
| 919 CallFunction(), | |
| 920 kNumberOfArguments, | |
| 921 kNoArgumentNames, | |
| 922 locs(), | |
| 923 ICData::Handle()); | 943 ICData::Handle()); |
| 924 ASSERT(locs()->out(0).reg() == EAX); | 944 ASSERT(locs()->out(0).reg() == EAX); |
| 925 } | 945 } |
| 926 | 946 |
| 927 | 947 |
| 928 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 948 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
| 929 bool opt) const { | 949 bool opt) const { |
| 930 const intptr_t kNumInputs = 1; | 950 const intptr_t kNumInputs = 1; |
| 931 return LocationSummary::Make(zone, | 951 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
| 932 kNumInputs, | |
| 933 Location::SameAsFirstInput(), | |
| 934 LocationSummary::kNoCall); | 952 LocationSummary::kNoCall); |
| 935 } | 953 } |
| 936 | 954 |
| 937 | 955 |
| 938 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 956 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 939 Register obj = locs()->in(0).reg(); | 957 Register obj = locs()->in(0).reg(); |
| 940 Register result = locs()->out(0).reg(); | 958 Register result = locs()->out(0).reg(); |
| 941 if (object()->definition()->representation() == kUntagged) { | 959 if (object()->definition()->representation() == kUntagged) { |
| 942 __ movl(result, Address(obj, offset())); | 960 __ movl(result, Address(obj, offset())); |
| 943 } else { | 961 } else { |
| 944 ASSERT(object()->definition()->representation() == kTagged); | 962 ASSERT(object()->definition()->representation() == kTagged); |
| 945 __ movl(result, FieldAddress(obj, offset())); | 963 __ movl(result, FieldAddress(obj, offset())); |
| 946 } | 964 } |
| 947 } | 965 } |
| 948 | 966 |
| 949 | 967 |
| 950 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 968 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
| 951 bool opt) const { | 969 bool opt) const { |
| 952 const intptr_t kNumInputs = 1; | 970 const intptr_t kNumInputs = 1; |
| 953 return LocationSummary::Make(zone, | 971 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 954 kNumInputs, | |
| 955 Location::RequiresRegister(), | |
| 956 LocationSummary::kNoCall); | 972 LocationSummary::kNoCall); |
| 957 } | 973 } |
| 958 | 974 |
| 959 | 975 |
| 960 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 976 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 961 const Register object = locs()->in(0).reg(); | 977 const Register object = locs()->in(0).reg(); |
| 962 const Register result = locs()->out(0).reg(); | 978 const Register result = locs()->out(0).reg(); |
| 963 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 979 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
| 964 if (CompileType::Smi().IsAssignableTo(value_type) || | 980 if (CompileType::Smi().IsAssignableTo(value_type) || |
| 965 value_type.IsTypeParameter()) { | 981 value_type.IsTypeParameter()) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 UNIMPLEMENTED(); | 1071 UNIMPLEMENTED(); |
| 1056 return kTagged; | 1072 return kTagged; |
| 1057 } | 1073 } |
| 1058 } | 1074 } |
| 1059 | 1075 |
| 1060 | 1076 |
| 1061 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 1077 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1062 bool opt) const { | 1078 bool opt) const { |
| 1063 const intptr_t kNumInputs = 2; | 1079 const intptr_t kNumInputs = 2; |
| 1064 const intptr_t kNumTemps = 0; | 1080 const intptr_t kNumTemps = 0; |
| 1065 LocationSummary* locs = new(zone) LocationSummary( | 1081 LocationSummary* locs = new (zone) |
| 1066 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1082 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1067 locs->set_in(0, Location::RequiresRegister()); | 1083 locs->set_in(0, Location::RequiresRegister()); |
| 1068 if (CanBeImmediateIndex(index(), class_id())) { | 1084 if (CanBeImmediateIndex(index(), class_id())) { |
| 1069 // CanBeImmediateIndex must return false for unsafe smis. | 1085 // CanBeImmediateIndex must return false for unsafe smis. |
| 1070 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1086 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1071 } else { | 1087 } else { |
| 1072 // The index is either untagged (element size == 1) or a smi (for all | 1088 // The index is either untagged (element size == 1) or a smi (for all |
| 1073 // element sizes > 1). | 1089 // element sizes > 1). |
| 1074 locs->set_in(1, (index_scale() == 1) | 1090 locs->set_in(1, (index_scale() == 1) ? Location::WritableRegister() |
| 1075 ? Location::WritableRegister() | 1091 : Location::RequiresRegister()); |
| 1076 : Location::RequiresRegister()); | |
| 1077 } | 1092 } |
| 1078 if ((representation() == kUnboxedDouble) || | 1093 if ((representation() == kUnboxedDouble) || |
| 1079 (representation() == kUnboxedFloat32x4) || | 1094 (representation() == kUnboxedFloat32x4) || |
| 1080 (representation() == kUnboxedInt32x4) || | 1095 (representation() == kUnboxedInt32x4) || |
| 1081 (representation() == kUnboxedFloat64x2)) { | 1096 (representation() == kUnboxedFloat64x2)) { |
| 1082 locs->set_out(0, Location::RequiresFpuRegister()); | 1097 locs->set_out(0, Location::RequiresFpuRegister()); |
| 1083 } else if (representation() == kUnboxedUint32) { | 1098 } else if (representation() == kUnboxedUint32) { |
| 1084 ASSERT(class_id() == kTypedDataUint32ArrayCid); | 1099 ASSERT(class_id() == kTypedDataUint32ArrayCid); |
| 1085 locs->set_out(0, Location::RequiresRegister()); | 1100 locs->set_out(0, Location::RequiresRegister()); |
| 1086 } else if (representation() == kUnboxedInt32) { | 1101 } else if (representation() == kUnboxedInt32) { |
| 1087 ASSERT(class_id() == kTypedDataInt32ArrayCid); | 1102 ASSERT(class_id() == kTypedDataInt32ArrayCid); |
| 1088 locs->set_out(0, Location::RequiresRegister()); | 1103 locs->set_out(0, Location::RequiresRegister()); |
| 1089 } else { | 1104 } else { |
| 1090 ASSERT(representation() == kTagged); | 1105 ASSERT(representation() == kTagged); |
| 1091 locs->set_out(0, Location::RequiresRegister()); | 1106 locs->set_out(0, Location::RequiresRegister()); |
| 1092 } | 1107 } |
| 1093 return locs; | 1108 return locs; |
| 1094 } | 1109 } |
| 1095 | 1110 |
| 1096 | 1111 |
| 1097 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1112 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1098 // The array register points to the backing store for external arrays. | 1113 // The array register points to the backing store for external arrays. |
| 1099 const Register array = locs()->in(0).reg(); | 1114 const Register array = locs()->in(0).reg(); |
| 1100 const Location index = locs()->in(1); | 1115 const Location index = locs()->in(1); |
| 1101 | 1116 |
| 1102 Address element_address = index.IsRegister() | 1117 Address element_address = |
| 1103 ? Assembler::ElementAddressForRegIndex( | 1118 index.IsRegister() |
| 1104 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1119 ? Assembler::ElementAddressForRegIndex( |
| 1105 : Assembler::ElementAddressForIntIndex( | 1120 IsExternal(), class_id(), index_scale(), array, index.reg()) |
| 1106 IsExternal(), class_id(), index_scale(), | 1121 : Assembler::ElementAddressForIntIndex( |
| 1107 array, Smi::Cast(index.constant()).Value()); | 1122 IsExternal(), class_id(), index_scale(), array, |
| 1123 Smi::Cast(index.constant()).Value()); |
| 1108 | 1124 |
| 1109 if ((representation() == kUnboxedDouble) || | 1125 if ((representation() == kUnboxedDouble) || |
| 1110 (representation() == kUnboxedFloat32x4) || | 1126 (representation() == kUnboxedFloat32x4) || |
| 1111 (representation() == kUnboxedInt32x4) || | 1127 (representation() == kUnboxedInt32x4) || |
| 1112 (representation() == kUnboxedFloat64x2)) { | 1128 (representation() == kUnboxedFloat64x2)) { |
| 1113 XmmRegister result = locs()->out(0).fpu_reg(); | 1129 XmmRegister result = locs()->out(0).fpu_reg(); |
| 1114 if ((index_scale() == 1) && index.IsRegister()) { | 1130 if ((index_scale() == 1) && index.IsRegister()) { |
| 1115 __ SmiUntag(index.reg()); | 1131 __ SmiUntag(index.reg()); |
| 1116 } | 1132 } |
| 1117 switch (class_id()) { | 1133 switch (class_id()) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1135 if ((representation() == kUnboxedUint32) || | 1151 if ((representation() == kUnboxedUint32) || |
| 1136 (representation() == kUnboxedInt32)) { | 1152 (representation() == kUnboxedInt32)) { |
| 1137 Register result = locs()->out(0).reg(); | 1153 Register result = locs()->out(0).reg(); |
| 1138 if ((index_scale() == 1) && index.IsRegister()) { | 1154 if ((index_scale() == 1) && index.IsRegister()) { |
| 1139 __ SmiUntag(index.reg()); | 1155 __ SmiUntag(index.reg()); |
| 1140 } | 1156 } |
| 1141 switch (class_id()) { | 1157 switch (class_id()) { |
| 1142 case kTypedDataInt32ArrayCid: | 1158 case kTypedDataInt32ArrayCid: |
| 1143 ASSERT(representation() == kUnboxedInt32); | 1159 ASSERT(representation() == kUnboxedInt32); |
| 1144 __ movl(result, element_address); | 1160 __ movl(result, element_address); |
| 1145 break; | 1161 break; |
| 1146 case kTypedDataUint32ArrayCid: | 1162 case kTypedDataUint32ArrayCid: |
| 1147 ASSERT(representation() == kUnboxedUint32); | 1163 ASSERT(representation() == kUnboxedUint32); |
| 1148 __ movl(result, element_address); | 1164 __ movl(result, element_address); |
| 1149 break; | 1165 break; |
| 1150 default: | 1166 default: |
| 1151 UNREACHABLE(); | 1167 UNREACHABLE(); |
| 1152 } | 1168 } |
| 1153 return; | 1169 return; |
| 1154 } | 1170 } |
| 1155 | 1171 |
| 1156 ASSERT(representation() == kTagged); | 1172 ASSERT(representation() == kTagged); |
| 1157 | 1173 |
| 1158 Register result = locs()->out(0).reg(); | 1174 Register result = locs()->out(0).reg(); |
| 1159 if ((index_scale() == 1) && index.IsRegister()) { | 1175 if ((index_scale() == 1) && index.IsRegister()) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1189 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1205 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1190 __ movl(result, element_address); | 1206 __ movl(result, element_address); |
| 1191 break; | 1207 break; |
| 1192 } | 1208 } |
| 1193 } | 1209 } |
| 1194 | 1210 |
| 1195 | 1211 |
| 1196 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1212 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1197 intptr_t idx) const { | 1213 intptr_t idx) const { |
| 1198 // Array can be a Dart object or a pointer to external data. | 1214 // Array can be a Dart object or a pointer to external data. |
| 1199 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1215 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
| 1200 if (idx == 1) return kTagged; // Index is a smi. | 1216 if (idx == 1) return kTagged; // Index is a smi. |
| 1201 ASSERT(idx == 2); | 1217 ASSERT(idx == 2); |
| 1202 switch (class_id_) { | 1218 switch (class_id_) { |
| 1203 case kArrayCid: | 1219 case kArrayCid: |
| 1204 case kOneByteStringCid: | 1220 case kOneByteStringCid: |
| 1205 case kTypedDataInt8ArrayCid: | 1221 case kTypedDataInt8ArrayCid: |
| 1206 case kTypedDataUint8ArrayCid: | 1222 case kTypedDataUint8ArrayCid: |
| 1207 case kExternalTypedDataUint8ArrayCid: | 1223 case kExternalTypedDataUint8ArrayCid: |
| 1208 case kTypedDataUint8ClampedArrayCid: | 1224 case kTypedDataUint8ClampedArrayCid: |
| 1209 case kExternalTypedDataUint8ClampedArrayCid: | 1225 case kExternalTypedDataUint8ClampedArrayCid: |
| 1210 case kTypedDataInt16ArrayCid: | 1226 case kTypedDataInt16ArrayCid: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1227 UNIMPLEMENTED(); | 1243 UNIMPLEMENTED(); |
| 1228 return kTagged; | 1244 return kTagged; |
| 1229 } | 1245 } |
| 1230 } | 1246 } |
| 1231 | 1247 |
| 1232 | 1248 |
| 1233 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1249 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1234 bool opt) const { | 1250 bool opt) const { |
| 1235 const intptr_t kNumInputs = 3; | 1251 const intptr_t kNumInputs = 3; |
| 1236 const intptr_t kNumTemps = 0; | 1252 const intptr_t kNumTemps = 0; |
| 1237 LocationSummary* locs = new(zone) LocationSummary( | 1253 LocationSummary* locs = new (zone) |
| 1238 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1254 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1239 locs->set_in(0, Location::RequiresRegister()); | 1255 locs->set_in(0, Location::RequiresRegister()); |
| 1240 if (CanBeImmediateIndex(index(), class_id())) { | 1256 if (CanBeImmediateIndex(index(), class_id())) { |
| 1241 // CanBeImmediateIndex must return false for unsafe smis. | 1257 // CanBeImmediateIndex must return false for unsafe smis. |
| 1242 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1258 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1243 } else { | 1259 } else { |
| 1244 // The index is either untagged (element size == 1) or a smi (for all | 1260 // The index is either untagged (element size == 1) or a smi (for all |
| 1245 // element sizes > 1). | 1261 // element sizes > 1). |
| 1246 locs->set_in(1, (index_scale() == 1) | 1262 locs->set_in(1, (index_scale() == 1) ? Location::WritableRegister() |
| 1247 ? Location::WritableRegister() | 1263 : Location::RequiresRegister()); |
| 1248 : Location::RequiresRegister()); | |
| 1249 } | 1264 } |
| 1250 switch (class_id()) { | 1265 switch (class_id()) { |
| 1251 case kArrayCid: | 1266 case kArrayCid: |
| 1252 locs->set_in(2, ShouldEmitStoreBarrier() | 1267 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1253 ? Location::WritableRegister() | 1268 ? Location::WritableRegister() |
| 1254 : Location::RegisterOrConstant(value())); | 1269 : Location::RegisterOrConstant(value())); |
| 1255 break; | 1270 break; |
| 1256 case kExternalTypedDataUint8ArrayCid: | 1271 case kExternalTypedDataUint8ArrayCid: |
| 1257 case kExternalTypedDataUint8ClampedArrayCid: | 1272 case kExternalTypedDataUint8ClampedArrayCid: |
| 1258 case kTypedDataInt8ArrayCid: | 1273 case kTypedDataInt8ArrayCid: |
| 1259 case kTypedDataUint8ArrayCid: | 1274 case kTypedDataUint8ArrayCid: |
| 1260 case kTypedDataUint8ClampedArrayCid: | 1275 case kTypedDataUint8ClampedArrayCid: |
| 1261 case kOneByteStringCid: | 1276 case kOneByteStringCid: |
| 1262 // TODO(fschneider): Add location constraint for byte registers (EAX, | 1277 // TODO(fschneider): Add location constraint for byte registers (EAX, |
| 1263 // EBX, ECX, EDX) instead of using a fixed register. | 1278 // EBX, ECX, EDX) instead of using a fixed register. |
| 1264 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); | 1279 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1288 } | 1303 } |
| 1289 return locs; | 1304 return locs; |
| 1290 } | 1305 } |
| 1291 | 1306 |
| 1292 | 1307 |
| 1293 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1308 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1294 // The array register points to the backing store for external arrays. | 1309 // The array register points to the backing store for external arrays. |
| 1295 const Register array = locs()->in(0).reg(); | 1310 const Register array = locs()->in(0).reg(); |
| 1296 const Location index = locs()->in(1); | 1311 const Location index = locs()->in(1); |
| 1297 | 1312 |
| 1298 Address element_address = index.IsRegister() | 1313 Address element_address = |
| 1299 ? Assembler::ElementAddressForRegIndex( | 1314 index.IsRegister() |
| 1300 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1315 ? Assembler::ElementAddressForRegIndex( |
| 1301 : Assembler::ElementAddressForIntIndex( | 1316 IsExternal(), class_id(), index_scale(), array, index.reg()) |
| 1302 IsExternal(), class_id(), index_scale(), | 1317 : Assembler::ElementAddressForIntIndex( |
| 1303 array, Smi::Cast(index.constant()).Value()); | 1318 IsExternal(), class_id(), index_scale(), array, |
| 1319 Smi::Cast(index.constant()).Value()); |
| 1304 | 1320 |
| 1305 if ((index_scale() == 1) && index.IsRegister()) { | 1321 if ((index_scale() == 1) && index.IsRegister()) { |
| 1306 __ SmiUntag(index.reg()); | 1322 __ SmiUntag(index.reg()); |
| 1307 } | 1323 } |
| 1308 switch (class_id()) { | 1324 switch (class_id()) { |
| 1309 case kArrayCid: | 1325 case kArrayCid: |
| 1310 if (ShouldEmitStoreBarrier()) { | 1326 if (ShouldEmitStoreBarrier()) { |
| 1311 Register value = locs()->in(2).reg(); | 1327 Register value = locs()->in(2).reg(); |
| 1312 __ StoreIntoObject(array, element_address, value); | 1328 __ StoreIntoObject(array, element_address, value); |
| 1313 } else if (locs()->in(2).IsConstant()) { | 1329 } else if (locs()->in(2).IsConstant()) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1336 case kExternalTypedDataUint8ClampedArrayCid: { | 1352 case kExternalTypedDataUint8ClampedArrayCid: { |
| 1337 if (locs()->in(2).IsConstant()) { | 1353 if (locs()->in(2).IsConstant()) { |
| 1338 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1354 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1339 intptr_t value = constant.Value(); | 1355 intptr_t value = constant.Value(); |
| 1340 // Clamp to 0x0 or 0xFF respectively. | 1356 // Clamp to 0x0 or 0xFF respectively. |
| 1341 if (value > 0xFF) { | 1357 if (value > 0xFF) { |
| 1342 value = 0xFF; | 1358 value = 0xFF; |
| 1343 } else if (value < 0) { | 1359 } else if (value < 0) { |
| 1344 value = 0; | 1360 value = 0; |
| 1345 } | 1361 } |
| 1346 __ movb(element_address, | 1362 __ movb(element_address, Immediate(static_cast<int8_t>(value))); |
| 1347 Immediate(static_cast<int8_t>(value))); | |
| 1348 } else { | 1363 } else { |
| 1349 ASSERT(locs()->in(2).reg() == EAX); | 1364 ASSERT(locs()->in(2).reg() == EAX); |
| 1350 Label store_value, store_0xff; | 1365 Label store_value, store_0xff; |
| 1351 __ SmiUntag(EAX); | 1366 __ SmiUntag(EAX); |
| 1352 __ cmpl(EAX, Immediate(0xFF)); | 1367 __ cmpl(EAX, Immediate(0xFF)); |
| 1353 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); | 1368 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); |
| 1354 // Clamp to 0x0 or 0xFF respectively. | 1369 // Clamp to 0x0 or 0xFF respectively. |
| 1355 __ j(GREATER, &store_0xff); | 1370 __ j(GREATER, &store_0xff); |
| 1356 __ xorl(EAX, EAX); | 1371 __ xorl(EAX, EAX); |
| 1357 __ jmp(&store_value, Assembler::kNearJump); | 1372 __ jmp(&store_value, Assembler::kNearJump); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1392 | 1407 |
| 1393 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1408 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
| 1394 bool opt) const { | 1409 bool opt) const { |
| 1395 const intptr_t kNumInputs = 1; | 1410 const intptr_t kNumInputs = 1; |
| 1396 | 1411 |
| 1397 const intptr_t value_cid = value()->Type()->ToCid(); | 1412 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1398 const intptr_t field_cid = field().guarded_cid(); | 1413 const intptr_t field_cid = field().guarded_cid(); |
| 1399 | 1414 |
| 1400 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 1415 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
| 1401 const bool needs_value_cid_temp_reg = | 1416 const bool needs_value_cid_temp_reg = |
| 1402 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1417 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
| 1403 const bool needs_field_temp_reg = emit_full_guard; | 1418 const bool needs_field_temp_reg = emit_full_guard; |
| 1404 | 1419 |
| 1405 intptr_t num_temps = 0; | 1420 intptr_t num_temps = 0; |
| 1406 if (needs_value_cid_temp_reg) { | 1421 if (needs_value_cid_temp_reg) { |
| 1407 num_temps++; | 1422 num_temps++; |
| 1408 } | 1423 } |
| 1409 if (needs_field_temp_reg) { | 1424 if (needs_field_temp_reg) { |
| 1410 num_temps++; | 1425 num_temps++; |
| 1411 } | 1426 } |
| 1412 | 1427 |
| 1413 LocationSummary* summary = new(zone) LocationSummary( | 1428 LocationSummary* summary = new (zone) |
| 1414 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1429 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1415 summary->set_in(0, Location::RequiresRegister()); | 1430 summary->set_in(0, Location::RequiresRegister()); |
| 1416 | 1431 |
| 1417 for (intptr_t i = 0; i < num_temps; i++) { | 1432 for (intptr_t i = 0; i < num_temps; i++) { |
| 1418 summary->set_temp(i, Location::RequiresRegister()); | 1433 summary->set_temp(i, Location::RequiresRegister()); |
| 1419 } | 1434 } |
| 1420 | 1435 |
| 1421 return summary; | 1436 return summary; |
| 1422 } | 1437 } |
| 1423 | 1438 |
| 1424 | 1439 |
| 1425 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1440 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1426 ASSERT(sizeof(classid_t) == kInt16Size); | 1441 ASSERT(sizeof(classid_t) == kInt16Size); |
| 1427 const intptr_t value_cid = value()->Type()->ToCid(); | 1442 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1428 const intptr_t field_cid = field().guarded_cid(); | 1443 const intptr_t field_cid = field().guarded_cid(); |
| 1429 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1444 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 1430 | 1445 |
| 1431 if (field_cid == kDynamicCid) { | 1446 if (field_cid == kDynamicCid) { |
| 1432 if (Compiler::IsBackgroundCompilation()) { | 1447 if (Compiler::IsBackgroundCompilation()) { |
| 1433 // Field state changed while compiling. | 1448 // Field state changed while compiling. |
| 1434 Compiler::AbortBackgroundCompilation(deopt_id(), | 1449 Compiler::AbortBackgroundCompilation( |
| 1450 deopt_id(), |
| 1435 "GuardFieldClassInstr: field state changed while compiling"); | 1451 "GuardFieldClassInstr: field state changed while compiling"); |
| 1436 } | 1452 } |
| 1437 ASSERT(!compiler->is_optimizing()); | 1453 ASSERT(!compiler->is_optimizing()); |
| 1438 return; // Nothing to emit. | 1454 return; // Nothing to emit. |
| 1439 } | 1455 } |
| 1440 | 1456 |
| 1441 const bool emit_full_guard = | 1457 const bool emit_full_guard = |
| 1442 !compiler->is_optimizing() || (field_cid == kIllegalCid); | 1458 !compiler->is_optimizing() || (field_cid == kIllegalCid); |
| 1443 | 1459 |
| 1444 const bool needs_value_cid_temp_reg = | 1460 const bool needs_value_cid_temp_reg = |
| 1445 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1461 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
| 1446 | 1462 |
| 1447 const bool needs_field_temp_reg = emit_full_guard; | 1463 const bool needs_field_temp_reg = emit_full_guard; |
| 1448 | 1464 |
| 1449 const Register value_reg = locs()->in(0).reg(); | 1465 const Register value_reg = locs()->in(0).reg(); |
| 1450 | 1466 |
| 1451 const Register value_cid_reg = needs_value_cid_temp_reg ? | 1467 const Register value_cid_reg = |
| 1452 locs()->temp(0).reg() : kNoRegister; | 1468 needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister; |
| 1453 | 1469 |
| 1454 const Register field_reg = needs_field_temp_reg ? | 1470 const Register field_reg = needs_field_temp_reg |
| 1455 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1471 ? locs()->temp(locs()->temp_count() - 1).reg() |
| 1472 : kNoRegister; |
| 1456 | 1473 |
| 1457 Label ok, fail_label; | 1474 Label ok, fail_label; |
| 1458 | 1475 |
| 1459 Label* deopt = compiler->is_optimizing() ? | 1476 Label* deopt = |
| 1460 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1477 compiler->is_optimizing() |
| 1478 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1479 : NULL; |
| 1461 | 1480 |
| 1462 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1481 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
| 1463 | 1482 |
| 1464 if (emit_full_guard) { | 1483 if (emit_full_guard) { |
| 1465 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1484 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
| 1466 | 1485 |
| 1467 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | 1486 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
| 1468 FieldAddress field_nullability_operand( | 1487 FieldAddress field_nullability_operand(field_reg, |
| 1469 field_reg, Field::is_nullable_offset()); | 1488 Field::is_nullable_offset()); |
| 1470 | 1489 |
| 1471 if (value_cid == kDynamicCid) { | 1490 if (value_cid == kDynamicCid) { |
| 1472 LoadValueCid(compiler, value_cid_reg, value_reg); | 1491 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1473 __ cmpw(value_cid_reg, field_cid_operand); | 1492 __ cmpw(value_cid_reg, field_cid_operand); |
| 1474 __ j(EQUAL, &ok); | 1493 __ j(EQUAL, &ok); |
| 1475 __ cmpw(value_cid_reg, field_nullability_operand); | 1494 __ cmpw(value_cid_reg, field_nullability_operand); |
| 1476 } else if (value_cid == kNullCid) { | 1495 } else if (value_cid == kNullCid) { |
| 1477 // Value in graph known to be null. | 1496 // Value in graph known to be null. |
| 1478 // Compare with null. | 1497 // Compare with null. |
| 1479 __ cmpw(field_nullability_operand, Immediate(value_cid)); | 1498 __ cmpw(field_nullability_operand, Immediate(value_cid)); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1562 } | 1581 } |
| 1563 __ Bind(&ok); | 1582 __ Bind(&ok); |
| 1564 } | 1583 } |
| 1565 | 1584 |
| 1566 | 1585 |
| 1567 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1586 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
| 1568 bool opt) const { | 1587 bool opt) const { |
| 1569 const intptr_t kNumInputs = 1; | 1588 const intptr_t kNumInputs = 1; |
| 1570 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1589 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1571 const intptr_t kNumTemps = 3; | 1590 const intptr_t kNumTemps = 3; |
| 1572 LocationSummary* summary = new(zone) LocationSummary( | 1591 LocationSummary* summary = new (zone) |
| 1573 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1592 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1574 summary->set_in(0, Location::RequiresRegister()); | 1593 summary->set_in(0, Location::RequiresRegister()); |
| 1575 // We need temporaries for field object, length offset and expected length. | 1594 // We need temporaries for field object, length offset and expected length. |
| 1576 summary->set_temp(0, Location::RequiresRegister()); | 1595 summary->set_temp(0, Location::RequiresRegister()); |
| 1577 summary->set_temp(1, Location::RequiresRegister()); | 1596 summary->set_temp(1, Location::RequiresRegister()); |
| 1578 summary->set_temp(2, Location::RequiresRegister()); | 1597 summary->set_temp(2, Location::RequiresRegister()); |
| 1579 return summary; | 1598 return summary; |
| 1580 } else { | 1599 } else { |
| 1581 LocationSummary* summary = new(zone) LocationSummary( | 1600 LocationSummary* summary = new (zone) |
| 1582 zone, kNumInputs, 0, LocationSummary::kNoCall); | 1601 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 1583 summary->set_in(0, Location::RequiresRegister()); | 1602 summary->set_in(0, Location::RequiresRegister()); |
| 1584 return summary; | 1603 return summary; |
| 1585 } | 1604 } |
| 1586 UNREACHABLE(); | 1605 UNREACHABLE(); |
| 1587 } | 1606 } |
| 1588 | 1607 |
| 1589 | 1608 |
| 1590 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1609 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1591 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1610 if (field().guarded_list_length() == Field::kNoFixedLength) { |
| 1592 if (Compiler::IsBackgroundCompilation()) { | 1611 if (Compiler::IsBackgroundCompilation()) { |
| 1593 // Field state changed while compiling. | 1612 // Field state changed while compiling. |
| 1594 Compiler::AbortBackgroundCompilation(deopt_id(), | 1613 Compiler::AbortBackgroundCompilation( |
| 1614 deopt_id(), |
| 1595 "GuardFieldLengthInstr: field state changed while compiling"); | 1615 "GuardFieldLengthInstr: field state changed while compiling"); |
| 1596 } | 1616 } |
| 1597 ASSERT(!compiler->is_optimizing()); | 1617 ASSERT(!compiler->is_optimizing()); |
| 1598 return; // Nothing to emit. | 1618 return; // Nothing to emit. |
| 1599 } | 1619 } |
| 1600 | 1620 |
| 1601 Label* deopt = compiler->is_optimizing() ? | 1621 Label* deopt = |
| 1602 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1622 compiler->is_optimizing() |
| 1623 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1624 : NULL; |
| 1603 | 1625 |
| 1604 const Register value_reg = locs()->in(0).reg(); | 1626 const Register value_reg = locs()->in(0).reg(); |
| 1605 | 1627 |
| 1606 if (!compiler->is_optimizing() || | 1628 if (!compiler->is_optimizing() || |
| 1607 (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1629 (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1608 const Register field_reg = locs()->temp(0).reg(); | 1630 const Register field_reg = locs()->temp(0).reg(); |
| 1609 const Register offset_reg = locs()->temp(1).reg(); | 1631 const Register offset_reg = locs()->temp(1).reg(); |
| 1610 const Register length_reg = locs()->temp(2).reg(); | 1632 const Register length_reg = locs()->temp(2).reg(); |
| 1611 | 1633 |
| 1612 Label ok; | 1634 Label ok; |
| 1613 | 1635 |
| 1614 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1636 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
| 1615 | 1637 |
| 1616 __ movsxb(offset_reg, FieldAddress(field_reg, | 1638 __ movsxb( |
| 1617 Field::guarded_list_length_in_object_offset_offset())); | 1639 offset_reg, |
| 1618 __ movl(length_reg, FieldAddress(field_reg, | 1640 FieldAddress(field_reg, |
| 1619 Field::guarded_list_length_offset())); | 1641 Field::guarded_list_length_in_object_offset_offset())); |
| 1642 __ movl(length_reg, |
| 1643 FieldAddress(field_reg, Field::guarded_list_length_offset())); |
| 1620 | 1644 |
| 1621 __ cmpl(offset_reg, Immediate(0)); | 1645 __ cmpl(offset_reg, Immediate(0)); |
| 1622 __ j(NEGATIVE, &ok); | 1646 __ j(NEGATIVE, &ok); |
| 1623 | 1647 |
| 1624 // Load the length from the value. GuardFieldClass already verified that | 1648 // Load the length from the value. GuardFieldClass already verified that |
| 1625 // value's class matches guarded class id of the field. | 1649 // value's class matches guarded class id of the field. |
| 1626 // offset_reg contains offset already corrected by -kHeapObjectTag that is | 1650 // offset_reg contains offset already corrected by -kHeapObjectTag that is |
| 1627 // why we use Address instead of FieldAddress. | 1651 // why we use Address instead of FieldAddress. |
| 1628 __ cmpl(length_reg, Address(value_reg, offset_reg, TIMES_1, 0)); | 1652 __ cmpl(length_reg, Address(value_reg, offset_reg, TIMES_1, 0)); |
| 1629 | 1653 |
| 1630 if (deopt == NULL) { | 1654 if (deopt == NULL) { |
| 1631 __ j(EQUAL, &ok); | 1655 __ j(EQUAL, &ok); |
| 1632 | 1656 |
| 1633 __ pushl(field_reg); | 1657 __ pushl(field_reg); |
| 1634 __ pushl(value_reg); | 1658 __ pushl(value_reg); |
| 1635 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1659 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
| 1636 __ Drop(2); // Drop the field and the value. | 1660 __ Drop(2); // Drop the field and the value. |
| 1637 } else { | 1661 } else { |
| 1638 __ j(NOT_EQUAL, deopt); | 1662 __ j(NOT_EQUAL, deopt); |
| 1639 } | 1663 } |
| 1640 | 1664 |
| 1641 __ Bind(&ok); | 1665 __ Bind(&ok); |
| 1642 } else { | 1666 } else { |
| 1643 ASSERT(compiler->is_optimizing()); | 1667 ASSERT(compiler->is_optimizing()); |
| 1644 ASSERT(field().guarded_list_length() >= 0); | 1668 ASSERT(field().guarded_list_length() >= 0); |
| 1645 ASSERT(field().guarded_list_length_in_object_offset() != | 1669 ASSERT(field().guarded_list_length_in_object_offset() != |
| 1646 Field::kUnknownLengthOffset); | 1670 Field::kUnknownLengthOffset); |
| 1647 | 1671 |
| 1648 __ cmpl(FieldAddress(value_reg, | 1672 __ cmpl( |
| 1649 field().guarded_list_length_in_object_offset()), | 1673 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), |
| 1650 Immediate(Smi::RawValue(field().guarded_list_length()))); | 1674 Immediate(Smi::RawValue(field().guarded_list_length()))); |
| 1651 __ j(NOT_EQUAL, deopt); | 1675 __ j(NOT_EQUAL, deopt); |
| 1652 } | 1676 } |
| 1653 } | 1677 } |
| 1654 | 1678 |
| 1655 | 1679 |
| 1656 class BoxAllocationSlowPath : public SlowPathCode { | 1680 class BoxAllocationSlowPath : public SlowPathCode { |
| 1657 public: | 1681 public: |
| 1658 BoxAllocationSlowPath(Instruction* instruction, | 1682 BoxAllocationSlowPath(Instruction* instruction, |
| 1659 const Class& cls, | 1683 const Class& cls, |
| 1660 Register result) | 1684 Register result) |
| 1661 : instruction_(instruction), | 1685 : instruction_(instruction), cls_(cls), result_(result) {} |
| 1662 cls_(cls), | |
| 1663 result_(result) { } | |
| 1664 | 1686 |
| 1665 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1687 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1666 if (Assembler::EmittingComments()) { | 1688 if (Assembler::EmittingComments()) { |
| 1667 __ Comment("%s slow path allocation of %s", | 1689 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
| 1668 instruction_->DebugName(), | |
| 1669 String::Handle(cls_.ScrubbedName()).ToCString()); | 1690 String::Handle(cls_.ScrubbedName()).ToCString()); |
| 1670 } | 1691 } |
| 1671 __ Bind(entry_label()); | 1692 __ Bind(entry_label()); |
| 1672 const Code& stub = Code::ZoneHandle( | 1693 const Code& stub = Code::ZoneHandle( |
| 1673 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); | 1694 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); |
| 1674 const StubEntry stub_entry(stub); | 1695 const StubEntry stub_entry(stub); |
| 1675 | 1696 |
| 1676 LocationSummary* locs = instruction_->locs(); | 1697 LocationSummary* locs = instruction_->locs(); |
| 1677 | 1698 |
| 1678 locs->live_registers()->Remove(Location::RegisterLocation(result_)); | 1699 locs->live_registers()->Remove(Location::RegisterLocation(result_)); |
| 1679 | 1700 |
| 1680 compiler->SaveLiveRegisters(locs); | 1701 compiler->SaveLiveRegisters(locs); |
| 1681 compiler->GenerateCall(TokenPosition::kNoSource, | 1702 compiler->GenerateCall(TokenPosition::kNoSource, stub_entry, |
| 1682 stub_entry, | 1703 RawPcDescriptors::kOther, locs); |
| 1683 RawPcDescriptors::kOther, | |
| 1684 locs); | |
| 1685 compiler->AddStubCallTarget(stub); | 1704 compiler->AddStubCallTarget(stub); |
| 1686 __ MoveRegister(result_, EAX); | 1705 __ MoveRegister(result_, EAX); |
| 1687 compiler->RestoreLiveRegisters(locs); | 1706 compiler->RestoreLiveRegisters(locs); |
| 1688 __ jmp(exit_label()); | 1707 __ jmp(exit_label()); |
| 1689 } | 1708 } |
| 1690 | 1709 |
| 1691 static void Allocate(FlowGraphCompiler* compiler, | 1710 static void Allocate(FlowGraphCompiler* compiler, |
| 1692 Instruction* instruction, | 1711 Instruction* instruction, |
| 1693 const Class& cls, | 1712 const Class& cls, |
| 1694 Register result, | 1713 Register result, |
| 1695 Register temp) { | 1714 Register temp) { |
| 1696 if (compiler->intrinsic_mode()) { | 1715 if (compiler->intrinsic_mode()) { |
| 1697 __ TryAllocate(cls, | 1716 __ TryAllocate(cls, compiler->intrinsic_slow_path_label(), |
| 1698 compiler->intrinsic_slow_path_label(), | 1717 Assembler::kFarJump, result, temp); |
| 1699 Assembler::kFarJump, | |
| 1700 result, | |
| 1701 temp); | |
| 1702 } else { | 1718 } else { |
| 1703 BoxAllocationSlowPath* slow_path = | 1719 BoxAllocationSlowPath* slow_path = |
| 1704 new BoxAllocationSlowPath(instruction, cls, result); | 1720 new BoxAllocationSlowPath(instruction, cls, result); |
| 1705 compiler->AddSlowPathCode(slow_path); | 1721 compiler->AddSlowPathCode(slow_path); |
| 1706 | 1722 |
| 1707 __ TryAllocate(cls, | 1723 __ TryAllocate(cls, slow_path->entry_label(), Assembler::kFarJump, result, |
| 1708 slow_path->entry_label(), | |
| 1709 Assembler::kFarJump, | |
| 1710 result, | |
| 1711 temp); | 1724 temp); |
| 1712 __ Bind(slow_path->exit_label()); | 1725 __ Bind(slow_path->exit_label()); |
| 1713 } | 1726 } |
| 1714 } | 1727 } |
| 1715 | 1728 |
| 1716 private: | 1729 private: |
| 1717 Instruction* instruction_; | 1730 Instruction* instruction_; |
| 1718 const Class& cls_; | 1731 const Class& cls_; |
| 1719 const Register result_; | 1732 const Register result_; |
| 1720 }; | 1733 }; |
| 1721 | 1734 |
| 1722 | 1735 |
| 1723 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 1736 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
| 1724 bool opt) const { | 1737 bool opt) const { |
| 1725 const intptr_t kNumInputs = 2; | 1738 const intptr_t kNumInputs = 2; |
| 1726 const intptr_t kNumTemps = | 1739 const intptr_t kNumTemps = |
| 1727 (IsUnboxedStore() && opt) ? 2 : | 1740 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
| 1728 ((IsPotentialUnboxedStore()) ? 3 : 0); | 1741 LocationSummary* summary = new (zone) |
| 1729 LocationSummary* summary = new(zone) LocationSummary( | 1742 LocationSummary(zone, kNumInputs, kNumTemps, |
| 1730 zone, kNumInputs, kNumTemps, | 1743 ((IsUnboxedStore() && opt && is_initialization()) || |
| 1731 ((IsUnboxedStore() && opt && is_initialization()) || | 1744 IsPotentialUnboxedStore()) |
| 1732 IsPotentialUnboxedStore()) | 1745 ? LocationSummary::kCallOnSlowPath |
| 1733 ? LocationSummary::kCallOnSlowPath | 1746 : LocationSummary::kNoCall); |
| 1734 : LocationSummary::kNoCall); | |
| 1735 | 1747 |
| 1736 summary->set_in(0, Location::RequiresRegister()); | 1748 summary->set_in(0, Location::RequiresRegister()); |
| 1737 if (IsUnboxedStore() && opt) { | 1749 if (IsUnboxedStore() && opt) { |
| 1738 summary->set_in(1, Location::RequiresFpuRegister()); | 1750 summary->set_in(1, Location::RequiresFpuRegister()); |
| 1739 summary->set_temp(0, Location::RequiresRegister()); | 1751 summary->set_temp(0, Location::RequiresRegister()); |
| 1740 summary->set_temp(1, Location::RequiresRegister()); | 1752 summary->set_temp(1, Location::RequiresRegister()); |
| 1741 } else if (IsPotentialUnboxedStore()) { | 1753 } else if (IsPotentialUnboxedStore()) { |
| 1742 summary->set_in(1, ShouldEmitStoreBarrier() | 1754 summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister() |
| 1743 ? Location::WritableRegister() | 1755 : Location::RequiresRegister()); |
| 1744 : Location::RequiresRegister()); | |
| 1745 summary->set_temp(0, Location::RequiresRegister()); | 1756 summary->set_temp(0, Location::RequiresRegister()); |
| 1746 summary->set_temp(1, Location::RequiresRegister()); | 1757 summary->set_temp(1, Location::RequiresRegister()); |
| 1747 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 1758 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
| 1748 : Location::FpuRegisterLocation(XMM1)); | 1759 : Location::FpuRegisterLocation(XMM1)); |
| 1749 } else { | 1760 } else { |
| 1750 summary->set_in(1, ShouldEmitStoreBarrier() | 1761 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1751 ? Location::WritableRegister() | 1762 ? Location::WritableRegister() |
| 1752 : Location::RegisterOrConstant(value())); | 1763 : Location::RegisterOrConstant(value())); |
| 1753 } | 1764 } |
| 1754 return summary; | 1765 return summary; |
| 1755 } | 1766 } |
| 1756 | 1767 |
| 1757 | 1768 |
| 1758 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 1769 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
| 1759 StoreInstanceFieldInstr* instruction, | 1770 StoreInstanceFieldInstr* instruction, |
| 1760 Register box_reg, | 1771 Register box_reg, |
| 1761 const Class& cls, | 1772 const Class& cls, |
| 1762 Register instance_reg, | 1773 Register instance_reg, |
| 1763 intptr_t offset, | 1774 intptr_t offset, |
| 1764 Register temp) { | 1775 Register temp) { |
| 1765 Label done; | 1776 Label done; |
| 1766 const Immediate& raw_null = | 1777 const Immediate& raw_null = |
| 1767 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1778 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1768 __ movl(box_reg, FieldAddress(instance_reg, offset)); | 1779 __ movl(box_reg, FieldAddress(instance_reg, offset)); |
| 1769 __ cmpl(box_reg, raw_null); | 1780 __ cmpl(box_reg, raw_null); |
| 1770 __ j(NOT_EQUAL, &done); | 1781 __ j(NOT_EQUAL, &done); |
| 1771 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); | 1782 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
| 1772 __ movl(temp, box_reg); | 1783 __ movl(temp, box_reg); |
| 1773 __ StoreIntoObject(instance_reg, | 1784 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); |
| 1774 FieldAddress(instance_reg, offset), | |
| 1775 temp); | |
| 1776 | 1785 |
| 1777 __ Bind(&done); | 1786 __ Bind(&done); |
| 1778 } | 1787 } |
| 1779 | 1788 |
| 1780 | 1789 |
| 1781 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1790 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1782 ASSERT(sizeof(classid_t) == kInt16Size); | 1791 ASSERT(sizeof(classid_t) == kInt16Size); |
| 1783 Label skip_store; | 1792 Label skip_store; |
| 1784 | 1793 |
| 1785 Register instance_reg = locs()->in(0).reg(); | 1794 Register instance_reg = locs()->in(0).reg(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1802 case kFloat64x2Cid: | 1811 case kFloat64x2Cid: |
| 1803 cls = &compiler->float64x2_class(); | 1812 cls = &compiler->float64x2_class(); |
| 1804 break; | 1813 break; |
| 1805 default: | 1814 default: |
| 1806 UNREACHABLE(); | 1815 UNREACHABLE(); |
| 1807 } | 1816 } |
| 1808 | 1817 |
| 1809 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); | 1818 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); |
| 1810 __ movl(temp2, temp); | 1819 __ movl(temp2, temp); |
| 1811 __ StoreIntoObject(instance_reg, | 1820 __ StoreIntoObject(instance_reg, |
| 1812 FieldAddress(instance_reg, offset_in_bytes_), | 1821 FieldAddress(instance_reg, offset_in_bytes_), temp2); |
| 1813 temp2); | |
| 1814 } else { | 1822 } else { |
| 1815 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 1823 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes_)); |
| 1816 } | 1824 } |
| 1817 switch (cid) { | 1825 switch (cid) { |
| 1818 case kDoubleCid: | 1826 case kDoubleCid: |
| 1819 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); | 1827 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); |
| 1820 __ movsd(FieldAddress(temp, Double::value_offset()), value); | 1828 __ movsd(FieldAddress(temp, Double::value_offset()), value); |
| 1821 break; | 1829 break; |
| 1822 case kFloat32x4Cid: | 1830 case kFloat32x4Cid: |
| 1823 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); | 1831 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); |
| 1824 __ movups(FieldAddress(temp, Float32x4::value_offset()), value); | 1832 __ movups(FieldAddress(temp, Float32x4::value_offset()), value); |
| 1825 break; | 1833 break; |
| 1826 case kFloat64x2Cid: | 1834 case kFloat64x2Cid: |
| 1827 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); | 1835 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); |
| 1828 __ movups(FieldAddress(temp, Float64x2::value_offset()), value); | 1836 __ movups(FieldAddress(temp, Float64x2::value_offset()), value); |
| 1829 break; | 1837 break; |
| 1830 default: | 1838 default: |
| 1831 UNREACHABLE(); | 1839 UNREACHABLE(); |
| 1832 } | 1840 } |
| 1833 return; | 1841 return; |
| 1834 } | 1842 } |
| 1835 | 1843 |
| 1836 if (IsPotentialUnboxedStore()) { | 1844 if (IsPotentialUnboxedStore()) { |
| 1837 __ Comment("PotentialUnboxedStore"); | 1845 __ Comment("PotentialUnboxedStore"); |
| 1838 Register value_reg = locs()->in(1).reg(); | 1846 Register value_reg = locs()->in(1).reg(); |
| 1839 Register temp = locs()->temp(0).reg(); | 1847 Register temp = locs()->temp(0).reg(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1877 __ jmp(&store_pointer); | 1885 __ jmp(&store_pointer); |
| 1878 | 1886 |
| 1879 | 1887 |
| 1880 if (!compiler->is_optimizing()) { | 1888 if (!compiler->is_optimizing()) { |
| 1881 locs()->live_registers()->Add(locs()->in(0)); | 1889 locs()->live_registers()->Add(locs()->in(0)); |
| 1882 locs()->live_registers()->Add(locs()->in(1)); | 1890 locs()->live_registers()->Add(locs()->in(1)); |
| 1883 } | 1891 } |
| 1884 | 1892 |
| 1885 { | 1893 { |
| 1886 __ Bind(&store_double); | 1894 __ Bind(&store_double); |
| 1887 EnsureMutableBox(compiler, | 1895 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
| 1888 this, | 1896 instance_reg, offset_in_bytes_, temp2); |
| 1889 temp, | |
| 1890 compiler->double_class(), | |
| 1891 instance_reg, | |
| 1892 offset_in_bytes_, | |
| 1893 temp2); | |
| 1894 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); | 1897 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); |
| 1895 __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp); | 1898 __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp); |
| 1896 __ jmp(&skip_store); | 1899 __ jmp(&skip_store); |
| 1897 } | 1900 } |
| 1898 | 1901 |
| 1899 { | 1902 { |
| 1900 __ Bind(&store_float32x4); | 1903 __ Bind(&store_float32x4); |
| 1901 EnsureMutableBox(compiler, | 1904 EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(), |
| 1902 this, | 1905 instance_reg, offset_in_bytes_, temp2); |
| 1903 temp, | |
| 1904 compiler->float32x4_class(), | |
| 1905 instance_reg, | |
| 1906 offset_in_bytes_, | |
| 1907 temp2); | |
| 1908 __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset())); | 1906 __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset())); |
| 1909 __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp); | 1907 __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp); |
| 1910 __ jmp(&skip_store); | 1908 __ jmp(&skip_store); |
| 1911 } | 1909 } |
| 1912 | 1910 |
| 1913 { | 1911 { |
| 1914 __ Bind(&store_float64x2); | 1912 __ Bind(&store_float64x2); |
| 1915 EnsureMutableBox(compiler, | 1913 EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(), |
| 1916 this, | 1914 instance_reg, offset_in_bytes_, temp2); |
| 1917 temp, | |
| 1918 compiler->float64x2_class(), | |
| 1919 instance_reg, | |
| 1920 offset_in_bytes_, | |
| 1921 temp2); | |
| 1922 __ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset())); | 1915 __ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset())); |
| 1923 __ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp); | 1916 __ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp); |
| 1924 __ jmp(&skip_store); | 1917 __ jmp(&skip_store); |
| 1925 } | 1918 } |
| 1926 | 1919 |
| 1927 __ Bind(&store_pointer); | 1920 __ Bind(&store_pointer); |
| 1928 } | 1921 } |
| 1929 | 1922 |
| 1930 if (ShouldEmitStoreBarrier()) { | 1923 if (ShouldEmitStoreBarrier()) { |
| 1931 Register value_reg = locs()->in(1).reg(); | 1924 Register value_reg = locs()->in(1).reg(); |
| 1932 __ StoreIntoObject(instance_reg, | 1925 __ StoreIntoObject(instance_reg, |
| 1933 FieldAddress(instance_reg, offset_in_bytes_), | 1926 FieldAddress(instance_reg, offset_in_bytes_), value_reg, |
| 1934 value_reg, | |
| 1935 CanValueBeSmi()); | 1927 CanValueBeSmi()); |
| 1936 } else { | 1928 } else { |
| 1937 if (locs()->in(1).IsConstant()) { | 1929 if (locs()->in(1).IsConstant()) { |
| 1938 __ StoreIntoObjectNoBarrier( | 1930 __ StoreIntoObjectNoBarrier(instance_reg, |
| 1939 instance_reg, | 1931 FieldAddress(instance_reg, offset_in_bytes_), |
| 1940 FieldAddress(instance_reg, offset_in_bytes_), | 1932 locs()->in(1).constant()); |
| 1941 locs()->in(1).constant()); | |
| 1942 } else { | 1933 } else { |
| 1943 Register value_reg = locs()->in(1).reg(); | 1934 Register value_reg = locs()->in(1).reg(); |
| 1944 __ StoreIntoObjectNoBarrier(instance_reg, | 1935 __ StoreIntoObjectNoBarrier(instance_reg, |
| 1945 FieldAddress(instance_reg, offset_in_bytes_), | 1936 FieldAddress(instance_reg, offset_in_bytes_), |
| 1946 value_reg); | 1937 value_reg); |
| 1947 } | 1938 } |
| 1948 } | 1939 } |
| 1949 __ Bind(&skip_store); | 1940 __ Bind(&skip_store); |
| 1950 } | 1941 } |
| 1951 | 1942 |
| 1952 | 1943 |
| 1953 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1944 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 1954 bool opt) const { | 1945 bool opt) const { |
| 1955 const intptr_t kNumInputs = 1; | 1946 const intptr_t kNumInputs = 1; |
| 1956 const intptr_t kNumTemps = 0; | 1947 const intptr_t kNumTemps = 0; |
| 1957 LocationSummary* summary = new(zone) LocationSummary( | 1948 LocationSummary* summary = new (zone) |
| 1958 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1949 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1959 summary->set_in(0, Location::RequiresRegister()); | 1950 summary->set_in(0, Location::RequiresRegister()); |
| 1960 // By specifying same register as input, our simple register allocator can | 1951 // By specifying same register as input, our simple register allocator can |
| 1961 // generate better code. | 1952 // generate better code. |
| 1962 summary->set_out(0, Location::SameAsFirstInput()); | 1953 summary->set_out(0, Location::SameAsFirstInput()); |
| 1963 return summary; | 1954 return summary; |
| 1964 } | 1955 } |
| 1965 | 1956 |
| 1966 | 1957 |
| 1967 // When the parser is building an implicit static getter for optimization, | 1958 // When the parser is building an implicit static getter for optimization, |
| 1968 // it can generate a function body where deoptimization ids do not line up | 1959 // it can generate a function body where deoptimization ids do not line up |
| 1969 // with the unoptimized code. | 1960 // with the unoptimized code. |
| 1970 // | 1961 // |
| 1971 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 1962 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 1972 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1963 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1973 Register field = locs()->in(0).reg(); | 1964 Register field = locs()->in(0).reg(); |
| 1974 Register result = locs()->out(0).reg(); | 1965 Register result = locs()->out(0).reg(); |
| 1975 __ movl(result, FieldAddress(field, Field::static_value_offset())); | 1966 __ movl(result, FieldAddress(field, Field::static_value_offset())); |
| 1976 } | 1967 } |
| 1977 | 1968 |
| 1978 | 1969 |
| 1979 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1970 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 1980 bool opt) const { | 1971 bool opt) const { |
| 1981 LocationSummary* locs = new(zone) LocationSummary( | 1972 LocationSummary* locs = |
| 1982 zone, 1, 1, LocationSummary::kNoCall); | 1973 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
| 1983 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 1974 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 1984 : Location::RequiresRegister()); | 1975 : Location::RequiresRegister()); |
| 1985 locs->set_temp(0, Location::RequiresRegister()); | 1976 locs->set_temp(0, Location::RequiresRegister()); |
| 1986 return locs; | 1977 return locs; |
| 1987 } | 1978 } |
| 1988 | 1979 |
| 1989 | 1980 |
| 1990 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1981 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1991 Register value = locs()->in(0).reg(); | 1982 Register value = locs()->in(0).reg(); |
| 1992 Register temp = locs()->temp(0).reg(); | 1983 Register temp = locs()->temp(0).reg(); |
| 1993 | 1984 |
| 1994 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 1985 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
| 1995 if (this->value()->NeedsStoreBuffer()) { | 1986 if (this->value()->NeedsStoreBuffer()) { |
| 1996 __ StoreIntoObject(temp, | 1987 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
| 1997 FieldAddress(temp, Field::static_value_offset()), | 1988 value, CanValueBeSmi()); |
| 1998 value, | |
| 1999 CanValueBeSmi()); | |
| 2000 } else { | 1989 } else { |
| 2001 __ StoreIntoObjectNoBarrier( | 1990 __ StoreIntoObjectNoBarrier( |
| 2002 temp, FieldAddress(temp, Field::static_value_offset()), value); | 1991 temp, FieldAddress(temp, Field::static_value_offset()), value); |
| 2003 } | 1992 } |
| 2004 } | 1993 } |
| 2005 | 1994 |
| 2006 | 1995 |
| 2007 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 1996 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
| 2008 bool opt) const { | 1997 bool opt) const { |
| 2009 const intptr_t kNumInputs = 2; | 1998 const intptr_t kNumInputs = 2; |
| 2010 const intptr_t kNumTemps = 0; | 1999 const intptr_t kNumTemps = 0; |
| 2011 LocationSummary* summary = new(zone) LocationSummary( | 2000 LocationSummary* summary = new (zone) |
| 2012 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2001 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2013 summary->set_in(0, Location::RegisterLocation(EAX)); | 2002 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 2014 summary->set_in(1, Location::RegisterLocation(EDX)); | 2003 summary->set_in(1, Location::RegisterLocation(EDX)); |
| 2015 summary->set_out(0, Location::RegisterLocation(EAX)); | 2004 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 2016 return summary; | 2005 return summary; |
| 2017 } | 2006 } |
| 2018 | 2007 |
| 2019 | 2008 |
| 2020 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2009 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2021 ASSERT(locs()->in(0).reg() == EAX); // Value. | 2010 ASSERT(locs()->in(0).reg() == EAX); // Value. |
| 2022 ASSERT(locs()->in(1).reg() == EDX); // Instantiator type arguments. | 2011 ASSERT(locs()->in(1).reg() == EDX); // Instantiator type arguments. |
| 2023 | 2012 |
| 2024 compiler->GenerateInstanceOf(token_pos(), | 2013 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(), |
| 2025 deopt_id(), | |
| 2026 type(), | |
| 2027 negate_result(), | |
| 2028 locs()); | 2014 locs()); |
| 2029 ASSERT(locs()->out(0).reg() == EAX); | 2015 ASSERT(locs()->out(0).reg() == EAX); |
| 2030 } | 2016 } |
| 2031 | 2017 |
| 2032 | 2018 |
| 2033 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and | 2019 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and |
| 2034 // use slow path stub. | 2020 // use slow path stub. |
| 2035 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 2021 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
| 2036 bool opt) const { | 2022 bool opt) const { |
| 2037 const intptr_t kNumInputs = 2; | 2023 const intptr_t kNumInputs = 2; |
| 2038 const intptr_t kNumTemps = 0; | 2024 const intptr_t kNumTemps = 0; |
| 2039 LocationSummary* locs = new(zone) LocationSummary( | 2025 LocationSummary* locs = new (zone) |
| 2040 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2026 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2041 locs->set_in(0, Location::RegisterLocation(ECX)); | 2027 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 2042 locs->set_in(1, Location::RegisterLocation(EDX)); | 2028 locs->set_in(1, Location::RegisterLocation(EDX)); |
| 2043 locs->set_out(0, Location::RegisterLocation(EAX)); | 2029 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2044 return locs; | 2030 return locs; |
| 2045 } | 2031 } |
| 2046 | 2032 |
| 2047 | 2033 |
| 2048 // Inlines array allocation for known constant values. | 2034 // Inlines array allocation for known constant values. |
| 2049 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 2035 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
| 2050 intptr_t num_elements, | 2036 intptr_t num_elements, |
| 2051 Label* slow_path, | 2037 Label* slow_path, |
| 2052 Label* done) { | 2038 Label* done) { |
| 2053 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 2039 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
| 2054 const Register kLengthReg = EDX; | 2040 const Register kLengthReg = EDX; |
| 2055 const Register kElemTypeReg = ECX; | 2041 const Register kElemTypeReg = ECX; |
| 2056 const intptr_t instance_size = Array::InstanceSize(num_elements); | 2042 const intptr_t instance_size = Array::InstanceSize(num_elements); |
| 2057 | 2043 |
| 2058 // Instance in EAX. | 2044 // Instance in EAX. |
| 2059 // Object end address in EBX. | 2045 // Object end address in EBX. |
| 2060 __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump, | 2046 __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump, |
| 2061 EAX, // instance | 2047 EAX, // instance |
| 2062 EBX, // end address | 2048 EBX, // end address |
| 2063 EDI); // temp | 2049 EDI); // temp |
| 2064 | 2050 |
| 2065 // Store the type argument field. | 2051 // Store the type argument field. |
| 2066 __ StoreIntoObjectNoBarrier(EAX, | 2052 __ StoreIntoObjectNoBarrier( |
| 2067 FieldAddress(EAX, Array::type_arguments_offset()), | 2053 EAX, FieldAddress(EAX, Array::type_arguments_offset()), kElemTypeReg); |
| 2068 kElemTypeReg); | |
| 2069 | 2054 |
| 2070 // Set the length field. | 2055 // Set the length field. |
| 2071 __ StoreIntoObjectNoBarrier(EAX, | 2056 __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, Array::length_offset()), |
| 2072 FieldAddress(EAX, Array::length_offset()), | |
| 2073 kLengthReg); | 2057 kLengthReg); |
| 2074 | 2058 |
| 2075 // Initialize all array elements to raw_null. | 2059 // Initialize all array elements to raw_null. |
| 2076 // EAX: new object start as a tagged pointer. | 2060 // EAX: new object start as a tagged pointer. |
| 2077 // EBX: new object end address. | 2061 // EBX: new object end address. |
| 2078 // EDI: iterator which initially points to the start of the variable | 2062 // EDI: iterator which initially points to the start of the variable |
| 2079 // data area to be initialized. | 2063 // data area to be initialized. |
| 2080 if (num_elements > 0) { | 2064 if (num_elements > 0) { |
| 2081 const intptr_t array_size = instance_size - sizeof(RawArray); | 2065 const intptr_t array_size = instance_size - sizeof(RawArray); |
| 2082 const Immediate& raw_null = | 2066 const Immediate& raw_null = |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2104 | 2088 |
| 2105 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2089 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2106 // Allocate the array. EDX = length, ECX = element type. | 2090 // Allocate the array. EDX = length, ECX = element type. |
| 2107 const Register kLengthReg = EDX; | 2091 const Register kLengthReg = EDX; |
| 2108 const Register kElemTypeReg = ECX; | 2092 const Register kElemTypeReg = ECX; |
| 2109 const Register kResultReg = EAX; | 2093 const Register kResultReg = EAX; |
| 2110 ASSERT(locs()->in(0).reg() == kElemTypeReg); | 2094 ASSERT(locs()->in(0).reg() == kElemTypeReg); |
| 2111 ASSERT(locs()->in(1).reg() == kLengthReg); | 2095 ASSERT(locs()->in(1).reg() == kLengthReg); |
| 2112 | 2096 |
| 2113 Label slow_path, done; | 2097 Label slow_path, done; |
| 2114 if (compiler->is_optimizing() && | 2098 if (compiler->is_optimizing() && num_elements()->BindsToConstant() && |
| 2115 num_elements()->BindsToConstant() && | |
| 2116 num_elements()->BoundConstant().IsSmi()) { | 2099 num_elements()->BoundConstant().IsSmi()) { |
| 2117 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 2100 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |
| 2118 if ((length >= 0) && (length <= Array::kMaxElements)) { | 2101 if ((length >= 0) && (length <= Array::kMaxElements)) { |
| 2119 Label slow_path, done; | 2102 Label slow_path, done; |
| 2120 InlineArrayAllocation(compiler, length, &slow_path, &done); | 2103 InlineArrayAllocation(compiler, length, &slow_path, &done); |
| 2121 __ Bind(&slow_path); | 2104 __ Bind(&slow_path); |
| 2122 __ PushObject(Object::null_object()); // Make room for the result. | 2105 __ PushObject(Object::null_object()); // Make room for the result. |
| 2123 __ pushl(kLengthReg); | 2106 __ pushl(kLengthReg); |
| 2124 __ pushl(kElemTypeReg); | 2107 __ pushl(kElemTypeReg); |
| 2125 compiler->GenerateRuntimeCall(token_pos(), | 2108 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2126 deopt_id(), | 2109 kAllocateArrayRuntimeEntry, 2, locs()); |
| 2127 kAllocateArrayRuntimeEntry, | |
| 2128 2, | |
| 2129 locs()); | |
| 2130 __ Drop(2); | 2110 __ Drop(2); |
| 2131 __ popl(kResultReg); | 2111 __ popl(kResultReg); |
| 2132 __ Bind(&done); | 2112 __ Bind(&done); |
| 2133 return; | 2113 return; |
| 2134 } | 2114 } |
| 2135 } | 2115 } |
| 2136 | 2116 |
| 2137 __ Bind(&slow_path); | 2117 __ Bind(&slow_path); |
| 2138 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2118 const Code& stub = Code::ZoneHandle(compiler->zone(), |
| 2139 StubCode::AllocateArray_entry()->code()); | 2119 StubCode::AllocateArray_entry()->code()); |
| 2140 compiler->AddStubCallTarget(stub); | 2120 compiler->AddStubCallTarget(stub); |
| 2141 compiler->GenerateCall(token_pos(), | 2121 compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(), |
| 2142 *StubCode::AllocateArray_entry(), | 2122 RawPcDescriptors::kOther, locs()); |
| 2143 RawPcDescriptors::kOther, | |
| 2144 locs()); | |
| 2145 __ Bind(&done); | 2123 __ Bind(&done); |
| 2146 ASSERT(locs()->out(0).reg() == kResultReg); | 2124 ASSERT(locs()->out(0).reg() == kResultReg); |
| 2147 } | 2125 } |
| 2148 | 2126 |
| 2149 | 2127 |
| 2150 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2128 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
| 2151 bool opt) const { | 2129 bool opt) const { |
| 2152 const intptr_t kNumInputs = 1; | 2130 const intptr_t kNumInputs = 1; |
| 2153 const intptr_t kNumTemps = | 2131 const intptr_t kNumTemps = |
| 2154 (IsUnboxedLoad() && opt) ? 1 : | 2132 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); |
| 2155 ((IsPotentialUnboxedLoad()) ? 2 : 0); | |
| 2156 | 2133 |
| 2157 LocationSummary* locs = new(zone) LocationSummary( | 2134 LocationSummary* locs = new (zone) LocationSummary( |
| 2158 zone, kNumInputs, kNumTemps, | 2135 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) |
| 2159 (opt && !IsPotentialUnboxedLoad()) | 2136 ? LocationSummary::kNoCall |
| 2160 ? LocationSummary::kNoCall | 2137 : LocationSummary::kCallOnSlowPath); |
| 2161 : LocationSummary::kCallOnSlowPath); | |
| 2162 | 2138 |
| 2163 locs->set_in(0, Location::RequiresRegister()); | 2139 locs->set_in(0, Location::RequiresRegister()); |
| 2164 | 2140 |
| 2165 if (IsUnboxedLoad() && opt) { | 2141 if (IsUnboxedLoad() && opt) { |
| 2166 locs->set_temp(0, Location::RequiresRegister()); | 2142 locs->set_temp(0, Location::RequiresRegister()); |
| 2167 } else if (IsPotentialUnboxedLoad()) { | 2143 } else if (IsPotentialUnboxedLoad()) { |
| 2168 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2144 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
| 2169 : Location::FpuRegisterLocation(XMM1)); | 2145 : Location::FpuRegisterLocation(XMM1)); |
| 2170 locs->set_temp(1, Location::RequiresRegister()); | 2146 locs->set_temp(1, Location::RequiresRegister()); |
| 2171 } | 2147 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2233 | 2209 |
| 2234 // Fall through. | 2210 // Fall through. |
| 2235 __ jmp(&load_pointer); | 2211 __ jmp(&load_pointer); |
| 2236 | 2212 |
| 2237 if (!compiler->is_optimizing()) { | 2213 if (!compiler->is_optimizing()) { |
| 2238 locs()->live_registers()->Add(locs()->in(0)); | 2214 locs()->live_registers()->Add(locs()->in(0)); |
| 2239 } | 2215 } |
| 2240 | 2216 |
| 2241 { | 2217 { |
| 2242 __ Bind(&load_double); | 2218 __ Bind(&load_double); |
| 2243 BoxAllocationSlowPath::Allocate( | 2219 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
| 2244 compiler, this, compiler->double_class(), result, temp); | 2220 result, temp); |
| 2245 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2221 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2246 __ movsd(value, FieldAddress(temp, Double::value_offset())); | 2222 __ movsd(value, FieldAddress(temp, Double::value_offset())); |
| 2247 __ movsd(FieldAddress(result, Double::value_offset()), value); | 2223 __ movsd(FieldAddress(result, Double::value_offset()), value); |
| 2248 __ jmp(&done); | 2224 __ jmp(&done); |
| 2249 } | 2225 } |
| 2250 | 2226 |
| 2251 { | 2227 { |
| 2252 __ Bind(&load_float32x4); | 2228 __ Bind(&load_float32x4); |
| 2253 BoxAllocationSlowPath::Allocate( | 2229 BoxAllocationSlowPath::Allocate( |
| 2254 compiler, this, compiler->float32x4_class(), result, temp); | 2230 compiler, this, compiler->float32x4_class(), result, temp); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2272 } | 2248 } |
| 2273 __ movl(result, FieldAddress(instance_reg, offset_in_bytes())); | 2249 __ movl(result, FieldAddress(instance_reg, offset_in_bytes())); |
| 2274 __ Bind(&done); | 2250 __ Bind(&done); |
| 2275 } | 2251 } |
| 2276 | 2252 |
| 2277 | 2253 |
| 2278 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2254 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
| 2279 bool opt) const { | 2255 bool opt) const { |
| 2280 const intptr_t kNumInputs = 1; | 2256 const intptr_t kNumInputs = 1; |
| 2281 const intptr_t kNumTemps = 0; | 2257 const intptr_t kNumTemps = 0; |
| 2282 LocationSummary* locs = new(zone) LocationSummary( | 2258 LocationSummary* locs = new (zone) |
| 2283 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2259 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2284 locs->set_in(0, Location::RegisterLocation(EAX)); | 2260 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 2285 locs->set_out(0, Location::RegisterLocation(EAX)); | 2261 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2286 return locs; | 2262 return locs; |
| 2287 } | 2263 } |
| 2288 | 2264 |
| 2289 | 2265 |
| 2290 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2266 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2291 Register instantiator_reg = locs()->in(0).reg(); | 2267 Register instantiator_reg = locs()->in(0).reg(); |
| 2292 Register result_reg = locs()->out(0).reg(); | 2268 Register result_reg = locs()->out(0).reg(); |
| 2293 | 2269 |
| 2294 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2270 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2295 // A runtime call to instantiate the type is required. | 2271 // A runtime call to instantiate the type is required. |
| 2296 __ PushObject(Object::null_object()); // Make room for the result. | 2272 __ PushObject(Object::null_object()); // Make room for the result. |
| 2297 __ PushObject(type()); | 2273 __ PushObject(type()); |
| 2298 __ pushl(instantiator_reg); // Push instantiator type arguments. | 2274 __ pushl(instantiator_reg); // Push instantiator type arguments. |
| 2299 compiler->GenerateRuntimeCall(token_pos(), | 2275 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2300 deopt_id(), | 2276 kInstantiateTypeRuntimeEntry, 2, locs()); |
| 2301 kInstantiateTypeRuntimeEntry, | 2277 __ Drop(2); // Drop instantiator and uninstantiated type. |
| 2302 2, | |
| 2303 locs()); | |
| 2304 __ Drop(2); // Drop instantiator and uninstantiated type. | |
| 2305 __ popl(result_reg); // Pop instantiated type. | 2278 __ popl(result_reg); // Pop instantiated type. |
| 2306 ASSERT(instantiator_reg == result_reg); | 2279 ASSERT(instantiator_reg == result_reg); |
| 2307 } | 2280 } |
| 2308 | 2281 |
| 2309 | 2282 |
| 2310 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2283 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2311 Zone* zone, bool opt) const { | 2284 Zone* zone, |
| 2285 bool opt) const { |
| 2312 const intptr_t kNumInputs = 1; | 2286 const intptr_t kNumInputs = 1; |
| 2313 const intptr_t kNumTemps = 0; | 2287 const intptr_t kNumTemps = 0; |
| 2314 LocationSummary* locs = new(zone) LocationSummary( | 2288 LocationSummary* locs = new (zone) |
| 2315 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2289 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2316 locs->set_in(0, Location::RegisterLocation(EAX)); | 2290 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 2317 locs->set_out(0, Location::RegisterLocation(EAX)); | 2291 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2318 return locs; | 2292 return locs; |
| 2319 } | 2293 } |
| 2320 | 2294 |
| 2321 | 2295 |
| 2322 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2296 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2323 FlowGraphCompiler* compiler) { | 2297 FlowGraphCompiler* compiler) { |
| 2324 Register instantiator_reg = locs()->in(0).reg(); | 2298 Register instantiator_reg = locs()->in(0).reg(); |
| 2325 Register result_reg = locs()->out(0).reg(); | 2299 Register result_reg = locs()->out(0).reg(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2361 __ Bind(&found); | 2335 __ Bind(&found); |
| 2362 __ movl(EAX, Address(EDI, 1 * kWordSize)); // Cached instantiated args. | 2336 __ movl(EAX, Address(EDI, 1 * kWordSize)); // Cached instantiated args. |
| 2363 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); | 2337 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); |
| 2364 | 2338 |
| 2365 __ Bind(&slow_case); | 2339 __ Bind(&slow_case); |
| 2366 // Instantiate non-null type arguments. | 2340 // Instantiate non-null type arguments. |
| 2367 // A runtime call to instantiate the type arguments is required. | 2341 // A runtime call to instantiate the type arguments is required. |
| 2368 __ PushObject(Object::null_object()); // Make room for the result. | 2342 __ PushObject(Object::null_object()); // Make room for the result. |
| 2369 __ PushObject(type_arguments()); | 2343 __ PushObject(type_arguments()); |
| 2370 __ pushl(instantiator_reg); // Push instantiator type arguments. | 2344 __ pushl(instantiator_reg); // Push instantiator type arguments. |
| 2371 compiler->GenerateRuntimeCall(token_pos(), | 2345 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2372 deopt_id(), | 2346 kInstantiateTypeArgumentsRuntimeEntry, 2, |
| 2373 kInstantiateTypeArgumentsRuntimeEntry, | |
| 2374 2, | |
| 2375 locs()); | 2347 locs()); |
| 2376 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2348 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 2377 __ popl(result_reg); // Pop instantiated type arguments. | 2349 __ popl(result_reg); // Pop instantiated type arguments. |
| 2378 __ Bind(&type_arguments_instantiated); | 2350 __ Bind(&type_arguments_instantiated); |
| 2379 } | 2351 } |
| 2380 | 2352 |
| 2381 | 2353 |
| 2382 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2354 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
| 2383 Zone* zone, | 2355 Zone* zone, |
| 2384 bool opt) const { | 2356 bool opt) const { |
| 2385 ASSERT(opt); | 2357 ASSERT(opt); |
| 2386 const intptr_t kNumInputs = 0; | 2358 const intptr_t kNumInputs = 0; |
| 2387 const intptr_t kNumTemps = 2; | 2359 const intptr_t kNumTemps = 2; |
| 2388 LocationSummary* locs = new(zone) LocationSummary( | 2360 LocationSummary* locs = new (zone) LocationSummary( |
| 2389 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2361 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2390 locs->set_temp(0, Location::RegisterLocation(ECX)); | 2362 locs->set_temp(0, Location::RegisterLocation(ECX)); |
| 2391 locs->set_temp(1, Location::RegisterLocation(EDI)); | 2363 locs->set_temp(1, Location::RegisterLocation(EDI)); |
| 2392 locs->set_out(0, Location::RegisterLocation(EAX)); | 2364 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2393 return locs; | 2365 return locs; |
| 2394 } | 2366 } |
| 2395 | 2367 |
| 2396 | 2368 |
| 2397 class AllocateContextSlowPath : public SlowPathCode { | 2369 class AllocateContextSlowPath : public SlowPathCode { |
| 2398 public: | 2370 public: |
| 2399 explicit AllocateContextSlowPath( | 2371 explicit AllocateContextSlowPath( |
| 2400 AllocateUninitializedContextInstr* instruction) | 2372 AllocateUninitializedContextInstr* instruction) |
| 2401 : instruction_(instruction) { } | 2373 : instruction_(instruction) {} |
| 2402 | 2374 |
| 2403 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2375 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2404 __ Comment("AllocateContextSlowPath"); | 2376 __ Comment("AllocateContextSlowPath"); |
| 2405 __ Bind(entry_label()); | 2377 __ Bind(entry_label()); |
| 2406 | 2378 |
| 2407 LocationSummary* locs = instruction_->locs(); | 2379 LocationSummary* locs = instruction_->locs(); |
| 2408 ASSERT(!locs->live_registers()->Contains(locs->out(0))); | 2380 ASSERT(!locs->live_registers()->Contains(locs->out(0))); |
| 2409 | 2381 |
| 2410 compiler->SaveLiveRegisters(locs); | 2382 compiler->SaveLiveRegisters(locs); |
| 2411 | 2383 |
| 2412 __ movl(EDX, Immediate(instruction_->num_context_variables())); | 2384 __ movl(EDX, Immediate(instruction_->num_context_variables())); |
| 2413 const Code& stub = Code::ZoneHandle( | 2385 const Code& stub = Code::ZoneHandle( |
| 2414 compiler->zone(), StubCode::AllocateContext_entry()->code()); | 2386 compiler->zone(), StubCode::AllocateContext_entry()->code()); |
| 2415 compiler->AddStubCallTarget(stub); | 2387 compiler->AddStubCallTarget(stub); |
| 2416 compiler->GenerateCall(instruction_->token_pos(), | 2388 compiler->GenerateCall(instruction_->token_pos(), |
| 2417 *StubCode::AllocateContext_entry(), | 2389 *StubCode::AllocateContext_entry(), |
| 2418 RawPcDescriptors::kOther, | 2390 RawPcDescriptors::kOther, locs); |
| 2419 locs); | |
| 2420 ASSERT(instruction_->locs()->out(0).reg() == EAX); | 2391 ASSERT(instruction_->locs()->out(0).reg() == EAX); |
| 2421 compiler->RestoreLiveRegisters(instruction_->locs()); | 2392 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2422 __ jmp(exit_label()); | 2393 __ jmp(exit_label()); |
| 2423 } | 2394 } |
| 2424 | 2395 |
| 2425 private: | 2396 private: |
| 2426 AllocateUninitializedContextInstr* instruction_; | 2397 AllocateUninitializedContextInstr* instruction_; |
| 2427 }; | 2398 }; |
| 2428 | 2399 |
| 2429 | 2400 |
| 2430 void AllocateUninitializedContextInstr::EmitNativeCode( | 2401 void AllocateUninitializedContextInstr::EmitNativeCode( |
| 2431 FlowGraphCompiler* compiler) { | 2402 FlowGraphCompiler* compiler) { |
| 2432 ASSERT(compiler->is_optimizing()); | 2403 ASSERT(compiler->is_optimizing()); |
| 2433 Register temp = locs()->temp(0).reg(); | 2404 Register temp = locs()->temp(0).reg(); |
| 2434 Register temp2 = locs()->temp(1).reg(); | 2405 Register temp2 = locs()->temp(1).reg(); |
| 2435 Register result = locs()->out(0).reg(); | 2406 Register result = locs()->out(0).reg(); |
| 2436 // Try allocate the object. | 2407 // Try allocate the object. |
| 2437 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2408 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2438 compiler->AddSlowPathCode(slow_path); | 2409 compiler->AddSlowPathCode(slow_path); |
| 2439 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2410 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2440 | 2411 |
| 2441 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2412 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
| 2442 Assembler::kFarJump, | 2413 Assembler::kFarJump, |
| 2443 result, // instance | 2414 result, // instance |
| 2444 temp, // end address | 2415 temp, // end address |
| 2445 temp2); // temp | 2416 temp2); // temp |
| 2446 | 2417 |
| 2447 // Setup up number of context variables field. | 2418 // Setup up number of context variables field. |
| 2448 __ movl(FieldAddress(result, Context::num_variables_offset()), | 2419 __ movl(FieldAddress(result, Context::num_variables_offset()), |
| 2449 Immediate(num_context_variables())); | 2420 Immediate(num_context_variables())); |
| 2450 | 2421 |
| 2451 __ Bind(slow_path->exit_label()); | 2422 __ Bind(slow_path->exit_label()); |
| 2452 } | 2423 } |
| 2453 | 2424 |
| 2454 | 2425 |
| 2455 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2426 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
| 2456 bool opt) const { | 2427 bool opt) const { |
| 2457 const intptr_t kNumInputs = 0; | 2428 const intptr_t kNumInputs = 0; |
| 2458 const intptr_t kNumTemps = 1; | 2429 const intptr_t kNumTemps = 1; |
| 2459 LocationSummary* locs = new(zone) LocationSummary( | 2430 LocationSummary* locs = new (zone) |
| 2460 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2431 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2461 locs->set_temp(0, Location::RegisterLocation(EDX)); | 2432 locs->set_temp(0, Location::RegisterLocation(EDX)); |
| 2462 locs->set_out(0, Location::RegisterLocation(EAX)); | 2433 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2463 return locs; | 2434 return locs; |
| 2464 } | 2435 } |
| 2465 | 2436 |
| 2466 | 2437 |
| 2467 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2438 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2468 ASSERT(locs()->temp(0).reg() == EDX); | 2439 ASSERT(locs()->temp(0).reg() == EDX); |
| 2469 ASSERT(locs()->out(0).reg() == EAX); | 2440 ASSERT(locs()->out(0).reg() == EAX); |
| 2470 | 2441 |
| 2471 __ movl(EDX, Immediate(num_context_variables())); | 2442 __ movl(EDX, Immediate(num_context_variables())); |
| 2472 compiler->GenerateCall(token_pos(), | 2443 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
| 2473 *StubCode::AllocateContext_entry(), | 2444 RawPcDescriptors::kOther, locs()); |
| 2474 RawPcDescriptors::kOther, | |
| 2475 locs()); | |
| 2476 } | 2445 } |
| 2477 | 2446 |
| 2478 | 2447 |
| 2479 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2448 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2480 bool opt) const { | 2449 bool opt) const { |
| 2481 const intptr_t kNumInputs = 1; | 2450 const intptr_t kNumInputs = 1; |
| 2482 const intptr_t kNumTemps = 1; | 2451 const intptr_t kNumTemps = 1; |
| 2483 LocationSummary* locs = new(zone) LocationSummary( | 2452 LocationSummary* locs = new (zone) |
| 2484 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2453 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2485 locs->set_in(0, Location::RegisterLocation(EAX)); | 2454 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 2486 locs->set_temp(0, Location::RegisterLocation(ECX)); | 2455 locs->set_temp(0, Location::RegisterLocation(ECX)); |
| 2487 return locs; | 2456 return locs; |
| 2488 } | 2457 } |
| 2489 | 2458 |
| 2490 | 2459 |
| 2491 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2460 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2492 Register field = locs()->in(0).reg(); | 2461 Register field = locs()->in(0).reg(); |
| 2493 Register temp = locs()->temp(0).reg(); | 2462 Register temp = locs()->temp(0).reg(); |
| 2494 | 2463 |
| 2495 Label call_runtime, no_call; | 2464 Label call_runtime, no_call; |
| 2496 | 2465 |
| 2497 __ movl(temp, FieldAddress(field, Field::static_value_offset())); | 2466 __ movl(temp, FieldAddress(field, Field::static_value_offset())); |
| 2498 __ CompareObject(temp, Object::sentinel()); | 2467 __ CompareObject(temp, Object::sentinel()); |
| 2499 __ j(EQUAL, &call_runtime); | 2468 __ j(EQUAL, &call_runtime); |
| 2500 | 2469 |
| 2501 __ CompareObject(temp, Object::transition_sentinel()); | 2470 __ CompareObject(temp, Object::transition_sentinel()); |
| 2502 __ j(NOT_EQUAL, &no_call); | 2471 __ j(NOT_EQUAL, &no_call); |
| 2503 | 2472 |
| 2504 __ Bind(&call_runtime); | 2473 __ Bind(&call_runtime); |
| 2505 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2474 __ PushObject(Object::null_object()); // Make room for (unused) result. |
| 2506 __ pushl(field); | 2475 __ pushl(field); |
| 2507 compiler->GenerateRuntimeCall(token_pos(), | 2476 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2508 deopt_id(), | 2477 kInitStaticFieldRuntimeEntry, 1, locs()); |
| 2509 kInitStaticFieldRuntimeEntry, | |
| 2510 1, | |
| 2511 locs()); | |
| 2512 __ Drop(2); // Remove argument and unused result. | 2478 __ Drop(2); // Remove argument and unused result. |
| 2513 __ Bind(&no_call); | 2479 __ Bind(&no_call); |
| 2514 } | 2480 } |
| 2515 | 2481 |
| 2516 | 2482 |
| 2517 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2483 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
| 2518 bool opt) const { | 2484 bool opt) const { |
| 2519 const intptr_t kNumInputs = 1; | 2485 const intptr_t kNumInputs = 1; |
| 2520 const intptr_t kNumTemps = 0; | 2486 const intptr_t kNumTemps = 0; |
| 2521 LocationSummary* locs = new(zone) LocationSummary( | 2487 LocationSummary* locs = new (zone) |
| 2522 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2488 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2523 locs->set_in(0, Location::RegisterLocation(EAX)); | 2489 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 2524 locs->set_out(0, Location::RegisterLocation(EAX)); | 2490 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2525 return locs; | 2491 return locs; |
| 2526 } | 2492 } |
| 2527 | 2493 |
| 2528 | 2494 |
| 2529 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2495 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2530 Register context_value = locs()->in(0).reg(); | 2496 Register context_value = locs()->in(0).reg(); |
| 2531 Register result = locs()->out(0).reg(); | 2497 Register result = locs()->out(0).reg(); |
| 2532 | 2498 |
| 2533 __ PushObject(Object::null_object()); // Make room for the result. | 2499 __ PushObject(Object::null_object()); // Make room for the result. |
| 2534 __ pushl(context_value); | 2500 __ pushl(context_value); |
| 2535 compiler->GenerateRuntimeCall(token_pos(), | 2501 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2536 deopt_id(), | 2502 kCloneContextRuntimeEntry, 1, locs()); |
| 2537 kCloneContextRuntimeEntry, | |
| 2538 1, | |
| 2539 locs()); | |
| 2540 __ popl(result); // Remove argument. | 2503 __ popl(result); // Remove argument. |
| 2541 __ popl(result); // Get result (cloned context). | 2504 __ popl(result); // Get result (cloned context). |
| 2542 } | 2505 } |
| 2543 | 2506 |
| 2544 | 2507 |
| 2545 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2508 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
| 2546 bool opt) const { | 2509 bool opt) const { |
| 2547 UNREACHABLE(); | 2510 UNREACHABLE(); |
| 2548 return NULL; | 2511 return NULL; |
| 2549 } | 2512 } |
| 2550 | 2513 |
| 2551 | 2514 |
| 2552 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2515 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2553 __ Bind(compiler->GetJumpLabel(this)); | 2516 __ Bind(compiler->GetJumpLabel(this)); |
| 2554 compiler->AddExceptionHandler(catch_try_index(), | 2517 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
| 2555 try_index(), | |
| 2556 compiler->assembler()->CodeSize(), | 2518 compiler->assembler()->CodeSize(), |
| 2557 catch_handler_types_, | 2519 catch_handler_types_, needs_stacktrace()); |
| 2558 needs_stacktrace()); | |
| 2559 // On lazy deoptimization we patch the optimized code here to enter the | 2520 // On lazy deoptimization we patch the optimized code here to enter the |
| 2560 // deoptimization stub. | 2521 // deoptimization stub. |
| 2561 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2522 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
| 2562 if (compiler->is_optimizing()) { | 2523 if (compiler->is_optimizing()) { |
| 2563 compiler->AddDeoptIndexAtCall(deopt_id); | 2524 compiler->AddDeoptIndexAtCall(deopt_id); |
| 2564 } else { | 2525 } else { |
| 2565 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2526 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, |
| 2566 deopt_id, | |
| 2567 TokenPosition::kNoSource); | 2527 TokenPosition::kNoSource); |
| 2568 } | 2528 } |
| 2569 if (HasParallelMove()) { | 2529 if (HasParallelMove()) { |
| 2570 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2530 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 2571 } | 2531 } |
| 2572 | 2532 |
| 2573 // Restore ESP from EBP as we are coming from a throw and the code for | 2533 // Restore ESP from EBP as we are coming from a throw and the code for |
| 2574 // popping arguments has not been run. | 2534 // popping arguments has not been run. |
| 2575 const intptr_t fp_sp_dist = | 2535 const intptr_t fp_sp_dist = |
| 2576 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2536 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| 2577 ASSERT(fp_sp_dist <= 0); | 2537 ASSERT(fp_sp_dist <= 0); |
| 2578 __ leal(ESP, Address(EBP, fp_sp_dist)); | 2538 __ leal(ESP, Address(EBP, fp_sp_dist)); |
| 2579 | 2539 |
| 2580 // Restore stack and initialize the two exception variables: | 2540 // Restore stack and initialize the two exception variables: |
| 2581 // exception and stack trace variables. | 2541 // exception and stack trace variables. |
| 2582 __ movl(Address(EBP, exception_var().index() * kWordSize), | 2542 __ movl(Address(EBP, exception_var().index() * kWordSize), |
| 2583 kExceptionObjectReg); | 2543 kExceptionObjectReg); |
| 2584 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), | 2544 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), |
| 2585 kStackTraceObjectReg); | 2545 kStackTraceObjectReg); |
| 2586 } | 2546 } |
| 2587 | 2547 |
| 2588 | 2548 |
| 2589 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2549 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
| 2590 bool opt) const { | 2550 bool opt) const { |
| 2591 const intptr_t kNumInputs = 0; | 2551 const intptr_t kNumInputs = 0; |
| 2592 const intptr_t kNumTemps = opt ? 0 : 1; | 2552 const intptr_t kNumTemps = opt ? 0 : 1; |
| 2593 LocationSummary* summary = new(zone) LocationSummary( | 2553 LocationSummary* summary = new (zone) LocationSummary( |
| 2594 zone, kNumInputs, | 2554 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2595 kNumTemps, | |
| 2596 LocationSummary::kCallOnSlowPath); | |
| 2597 if (!opt) { | 2555 if (!opt) { |
| 2598 summary->set_temp(0, Location::RequiresRegister()); | 2556 summary->set_temp(0, Location::RequiresRegister()); |
| 2599 } | 2557 } |
| 2600 return summary; | 2558 return summary; |
| 2601 } | 2559 } |
| 2602 | 2560 |
| 2603 | 2561 |
| 2604 class CheckStackOverflowSlowPath : public SlowPathCode { | 2562 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 2605 public: | 2563 public: |
| 2606 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2564 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 2607 : instruction_(instruction) { } | 2565 : instruction_(instruction) {} |
| 2608 | 2566 |
| 2609 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2567 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2610 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2568 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
| 2611 __ Comment("CheckStackOverflowSlowPathOsr"); | 2569 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 2612 __ Bind(osr_entry_label()); | 2570 __ Bind(osr_entry_label()); |
| 2613 __ movl(Address(THR, Thread::stack_overflow_flags_offset()), | 2571 __ movl(Address(THR, Thread::stack_overflow_flags_offset()), |
| 2614 Immediate(Thread::kOsrRequest)); | 2572 Immediate(Thread::kOsrRequest)); |
| 2615 } | 2573 } |
| 2616 __ Comment("CheckStackOverflowSlowPath"); | 2574 __ Comment("CheckStackOverflowSlowPath"); |
| 2617 __ Bind(entry_label()); | 2575 __ Bind(entry_label()); |
| 2618 compiler->SaveLiveRegisters(instruction_->locs()); | 2576 compiler->SaveLiveRegisters(instruction_->locs()); |
| 2619 // pending_deoptimization_env_ is needed to generate a runtime call that | 2577 // pending_deoptimization_env_ is needed to generate a runtime call that |
| 2620 // may throw an exception. | 2578 // may throw an exception. |
| 2621 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2579 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
| 2622 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 2580 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
| 2623 compiler->pending_deoptimization_env_ = env; | 2581 compiler->pending_deoptimization_env_ = env; |
| 2624 compiler->GenerateRuntimeCall(instruction_->token_pos(), | 2582 compiler->GenerateRuntimeCall( |
| 2625 instruction_->deopt_id(), | 2583 instruction_->token_pos(), instruction_->deopt_id(), |
| 2626 kStackOverflowRuntimeEntry, | 2584 kStackOverflowRuntimeEntry, 0, instruction_->locs()); |
| 2627 0, | |
| 2628 instruction_->locs()); | |
| 2629 | 2585 |
| 2630 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { | 2586 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |
| 2631 // In unoptimized code, record loop stack checks as possible OSR entries. | 2587 // In unoptimized code, record loop stack checks as possible OSR entries. |
| 2632 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2588 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
| 2633 instruction_->deopt_id(), | 2589 instruction_->deopt_id(), |
| 2634 TokenPosition::kNoSource); | 2590 TokenPosition::kNoSource); |
| 2635 } | 2591 } |
| 2636 compiler->pending_deoptimization_env_ = NULL; | 2592 compiler->pending_deoptimization_env_ = NULL; |
| 2637 compiler->RestoreLiveRegisters(instruction_->locs()); | 2593 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2638 __ jmp(exit_label()); | 2594 __ jmp(exit_label()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2674 __ Bind(slow_path->exit_label()); | 2630 __ Bind(slow_path->exit_label()); |
| 2675 } | 2631 } |
| 2676 | 2632 |
| 2677 | 2633 |
| 2678 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2634 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 2679 BinarySmiOpInstr* shift_left) { | 2635 BinarySmiOpInstr* shift_left) { |
| 2680 const LocationSummary& locs = *shift_left->locs(); | 2636 const LocationSummary& locs = *shift_left->locs(); |
| 2681 Register left = locs.in(0).reg(); | 2637 Register left = locs.in(0).reg(); |
| 2682 Register result = locs.out(0).reg(); | 2638 Register result = locs.out(0).reg(); |
| 2683 ASSERT(left == result); | 2639 ASSERT(left == result); |
| 2684 Label* deopt = shift_left->CanDeoptimize() ? | 2640 Label* deopt = shift_left->CanDeoptimize() |
| 2685 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 2641 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 2686 : NULL; | 2642 ICData::kDeoptBinarySmiOp) |
| 2643 : NULL; |
| 2687 if (locs.in(1).IsConstant()) { | 2644 if (locs.in(1).IsConstant()) { |
| 2688 const Object& constant = locs.in(1).constant(); | 2645 const Object& constant = locs.in(1).constant(); |
| 2689 ASSERT(constant.IsSmi()); | 2646 ASSERT(constant.IsSmi()); |
| 2690 // shll operation masks the count to 5 bits. | 2647 // shll operation masks the count to 5 bits. |
| 2691 const intptr_t kCountLimit = 0x1F; | 2648 const intptr_t kCountLimit = 0x1F; |
| 2692 const intptr_t value = Smi::Cast(constant).Value(); | 2649 const intptr_t value = Smi::Cast(constant).Value(); |
| 2693 ASSERT((0 < value) && (value < kCountLimit)); | 2650 ASSERT((0 < value) && (value < kCountLimit)); |
| 2694 if (shift_left->can_overflow()) { | 2651 if (shift_left->can_overflow()) { |
| 2695 if (value == 1) { | 2652 if (value == 1) { |
| 2696 // Use overflow flag. | 2653 // Use overflow flag. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2723 if (left_int == 0) { | 2680 if (left_int == 0) { |
| 2724 __ cmpl(right, Immediate(0)); | 2681 __ cmpl(right, Immediate(0)); |
| 2725 __ j(NEGATIVE, deopt); | 2682 __ j(NEGATIVE, deopt); |
| 2726 return; | 2683 return; |
| 2727 } | 2684 } |
| 2728 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2685 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
| 2729 const bool right_needs_check = | 2686 const bool right_needs_check = |
| 2730 !RangeUtils::IsWithin(right_range, 0, max_right - 1); | 2687 !RangeUtils::IsWithin(right_range, 0, max_right - 1); |
| 2731 if (right_needs_check) { | 2688 if (right_needs_check) { |
| 2732 __ cmpl(right, | 2689 __ cmpl(right, |
| 2733 Immediate(reinterpret_cast<int32_t>(Smi::New(max_right)))); | 2690 Immediate(reinterpret_cast<int32_t>(Smi::New(max_right)))); |
| 2734 __ j(ABOVE_EQUAL, deopt); | 2691 __ j(ABOVE_EQUAL, deopt); |
| 2735 } | 2692 } |
| 2736 __ SmiUntag(right); | 2693 __ SmiUntag(right); |
| 2737 __ shll(left, right); | 2694 __ shll(left, right); |
| 2738 } | 2695 } |
| 2739 return; | 2696 return; |
| 2740 } | 2697 } |
| 2741 | 2698 |
| 2742 const bool right_needs_check = | 2699 const bool right_needs_check = |
| 2743 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); | 2700 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); |
| 2744 ASSERT(right == ECX); // Count must be in ECX | 2701 ASSERT(right == ECX); // Count must be in ECX |
| 2745 if (!shift_left->can_overflow()) { | 2702 if (!shift_left->can_overflow()) { |
| 2746 if (right_needs_check) { | 2703 if (right_needs_check) { |
| 2747 const bool right_may_be_negative = | 2704 const bool right_may_be_negative = |
| 2748 (right_range == NULL) || !right_range->IsPositive(); | 2705 (right_range == NULL) || !right_range->IsPositive(); |
| 2749 if (right_may_be_negative) { | 2706 if (right_may_be_negative) { |
| 2750 ASSERT(shift_left->CanDeoptimize()); | 2707 ASSERT(shift_left->CanDeoptimize()); |
| 2751 __ cmpl(right, Immediate(0)); | 2708 __ cmpl(right, Immediate(0)); |
| 2752 __ j(NEGATIVE, deopt); | 2709 __ j(NEGATIVE, deopt); |
| 2753 } | 2710 } |
| 2754 Label done, is_not_zero; | 2711 Label done, is_not_zero; |
| 2755 __ cmpl(right, | 2712 __ cmpl(right, |
| 2756 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | 2713 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
| 2757 __ j(BELOW, &is_not_zero, Assembler::kNearJump); | 2714 __ j(BELOW, &is_not_zero, Assembler::kNearJump); |
| 2758 __ xorl(left, left); | 2715 __ xorl(left, left); |
| 2759 __ jmp(&done, Assembler::kNearJump); | 2716 __ jmp(&done, Assembler::kNearJump); |
| 2760 __ Bind(&is_not_zero); | 2717 __ Bind(&is_not_zero); |
| 2761 __ SmiUntag(right); | 2718 __ SmiUntag(right); |
| 2762 __ shll(left, right); | 2719 __ shll(left, right); |
| 2763 __ Bind(&done); | 2720 __ Bind(&done); |
| 2764 } else { | 2721 } else { |
| 2765 __ SmiUntag(right); | 2722 __ SmiUntag(right); |
| 2766 __ shll(left, right); | 2723 __ shll(left, right); |
| 2767 } | 2724 } |
| 2768 } else { | 2725 } else { |
| 2769 if (right_needs_check) { | 2726 if (right_needs_check) { |
| 2770 ASSERT(shift_left->CanDeoptimize()); | 2727 ASSERT(shift_left->CanDeoptimize()); |
| 2771 __ cmpl(right, | 2728 __ cmpl(right, |
| 2772 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | 2729 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
| 2773 __ j(ABOVE_EQUAL, deopt); | 2730 __ j(ABOVE_EQUAL, deopt); |
| 2774 } | 2731 } |
| 2775 // Left is not a constant. | 2732 // Left is not a constant. |
| 2776 Register temp = locs.temp(0).reg(); | 2733 Register temp = locs.temp(0).reg(); |
| 2777 // Check if count too large for handling it inlined. | 2734 // Check if count too large for handling it inlined. |
| 2778 __ movl(temp, left); | 2735 __ movl(temp, left); |
| 2779 __ SmiUntag(right); | 2736 __ SmiUntag(right); |
| 2780 // Overflow test (preserve temp and right); | 2737 // Overflow test (preserve temp and right); |
| 2781 __ shll(left, right); | 2738 __ shll(left, right); |
| 2782 __ sarl(left, right); | 2739 __ sarl(left, right); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2796 } | 2753 } |
| 2797 | 2754 |
| 2798 | 2755 |
| 2799 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2756 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2800 // Only for precompiled code, not on ia32 currently. | 2757 // Only for precompiled code, not on ia32 currently. |
| 2801 UNIMPLEMENTED(); | 2758 UNIMPLEMENTED(); |
| 2802 } | 2759 } |
| 2803 | 2760 |
| 2804 | 2761 |
| 2805 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 2762 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
| 2806 Zone* zone, bool opt) const { | 2763 Zone* zone, |
| 2764 bool opt) const { |
| 2807 // Only for precompiled code, not on ia32 currently. | 2765 // Only for precompiled code, not on ia32 currently. |
| 2808 UNIMPLEMENTED(); | 2766 UNIMPLEMENTED(); |
| 2809 return NULL; | 2767 return NULL; |
| 2810 } | 2768 } |
| 2811 | 2769 |
| 2812 | 2770 |
| 2813 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 2771 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
| 2814 FlowGraphCompiler* compiler, BranchLabels labels) { | 2772 FlowGraphCompiler* compiler, |
| 2773 BranchLabels labels) { |
| 2815 // Only for precompiled code, not on ia32 currently. | 2774 // Only for precompiled code, not on ia32 currently. |
| 2816 UNIMPLEMENTED(); | 2775 UNIMPLEMENTED(); |
| 2817 return ZERO; | 2776 return ZERO; |
| 2818 } | 2777 } |
| 2819 | 2778 |
| 2820 | 2779 |
| 2821 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 2780 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 2822 BranchInstr* instr) { | 2781 BranchInstr* instr) { |
| 2823 // Only for precompiled code, not on ia32 currently. | 2782 // Only for precompiled code, not on ia32 currently. |
| 2824 UNIMPLEMENTED(); | 2783 UNIMPLEMENTED(); |
| 2825 } | 2784 } |
| 2826 | 2785 |
| 2827 | 2786 |
| 2828 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2787 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2829 // Only for precompiled code, not on ia32 currently. | 2788 // Only for precompiled code, not on ia32 currently. |
| 2830 UNIMPLEMENTED(); | 2789 UNIMPLEMENTED(); |
| 2831 } | 2790 } |
| 2832 | 2791 |
| 2833 | 2792 |
| 2834 static bool IsSmiValue(const Object& constant, intptr_t value) { | 2793 static bool IsSmiValue(const Object& constant, intptr_t value) { |
| 2835 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); | 2794 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); |
| 2836 } | 2795 } |
| 2837 | 2796 |
| 2838 | 2797 |
| 2839 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 2798 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 2840 bool opt) const { | 2799 bool opt) const { |
| 2841 const intptr_t kNumInputs = 2; | 2800 const intptr_t kNumInputs = 2; |
| 2842 if (op_kind() == Token::kTRUNCDIV) { | 2801 if (op_kind() == Token::kTRUNCDIV) { |
| 2843 const intptr_t kNumTemps = 1; | 2802 const intptr_t kNumTemps = 1; |
| 2844 LocationSummary* summary = new(zone) LocationSummary( | 2803 LocationSummary* summary = new (zone) |
| 2845 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2804 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2846 if (RightIsPowerOfTwoConstant()) { | 2805 if (RightIsPowerOfTwoConstant()) { |
| 2847 summary->set_in(0, Location::RequiresRegister()); | 2806 summary->set_in(0, Location::RequiresRegister()); |
| 2848 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 2807 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 2849 // The programmer only controls one bit, so the constant is safe. | 2808 // The programmer only controls one bit, so the constant is safe. |
| 2850 summary->set_in(1, Location::Constant(right_constant)); | 2809 summary->set_in(1, Location::Constant(right_constant)); |
| 2851 summary->set_temp(0, Location::RequiresRegister()); | 2810 summary->set_temp(0, Location::RequiresRegister()); |
| 2852 summary->set_out(0, Location::SameAsFirstInput()); | 2811 summary->set_out(0, Location::SameAsFirstInput()); |
| 2853 } else { | 2812 } else { |
| 2854 // Both inputs must be writable because they will be untagged. | 2813 // Both inputs must be writable because they will be untagged. |
| 2855 summary->set_in(0, Location::RegisterLocation(EAX)); | 2814 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 2856 summary->set_in(1, Location::WritableRegister()); | 2815 summary->set_in(1, Location::WritableRegister()); |
| 2857 summary->set_out(0, Location::SameAsFirstInput()); | 2816 summary->set_out(0, Location::SameAsFirstInput()); |
| 2858 // Will be used for sign extension and division. | 2817 // Will be used for sign extension and division. |
| 2859 summary->set_temp(0, Location::RegisterLocation(EDX)); | 2818 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 2860 } | 2819 } |
| 2861 return summary; | 2820 return summary; |
| 2862 } else if (op_kind() == Token::kMOD) { | 2821 } else if (op_kind() == Token::kMOD) { |
| 2863 const intptr_t kNumTemps = 1; | 2822 const intptr_t kNumTemps = 1; |
| 2864 LocationSummary* summary = new(zone) LocationSummary( | 2823 LocationSummary* summary = new (zone) |
| 2865 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2824 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2866 // Both inputs must be writable because they will be untagged. | 2825 // Both inputs must be writable because they will be untagged. |
| 2867 summary->set_in(0, Location::RegisterLocation(EDX)); | 2826 summary->set_in(0, Location::RegisterLocation(EDX)); |
| 2868 summary->set_in(1, Location::WritableRegister()); | 2827 summary->set_in(1, Location::WritableRegister()); |
| 2869 summary->set_out(0, Location::SameAsFirstInput()); | 2828 summary->set_out(0, Location::SameAsFirstInput()); |
| 2870 // Will be used for sign extension and division. | 2829 // Will be used for sign extension and division. |
| 2871 summary->set_temp(0, Location::RegisterLocation(EAX)); | 2830 summary->set_temp(0, Location::RegisterLocation(EAX)); |
| 2872 return summary; | 2831 return summary; |
| 2873 } else if (op_kind() == Token::kSHR) { | 2832 } else if (op_kind() == Token::kSHR) { |
| 2874 const intptr_t kNumTemps = 0; | 2833 const intptr_t kNumTemps = 0; |
| 2875 LocationSummary* summary = new(zone) LocationSummary( | 2834 LocationSummary* summary = new (zone) |
| 2876 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2835 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2877 summary->set_in(0, Location::RequiresRegister()); | 2836 summary->set_in(0, Location::RequiresRegister()); |
| 2878 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 2837 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 2879 summary->set_out(0, Location::SameAsFirstInput()); | 2838 summary->set_out(0, Location::SameAsFirstInput()); |
| 2880 return summary; | 2839 return summary; |
| 2881 } else if (op_kind() == Token::kSHL) { | 2840 } else if (op_kind() == Token::kSHL) { |
| 2882 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 2841 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 2883 // Shift-by-1 overflow checking can use flags, otherwise we need a temp. | 2842 // Shift-by-1 overflow checking can use flags, otherwise we need a temp. |
| 2884 const bool shiftBy1 = | 2843 const bool shiftBy1 = |
| 2885 (right_constant != NULL) && IsSmiValue(right_constant->value(), 1); | 2844 (right_constant != NULL) && IsSmiValue(right_constant->value(), 1); |
| 2886 const intptr_t kNumTemps = (can_overflow() && !shiftBy1) ? 1 : 0; | 2845 const intptr_t kNumTemps = (can_overflow() && !shiftBy1) ? 1 : 0; |
| 2887 LocationSummary* summary = new(zone) LocationSummary( | 2846 LocationSummary* summary = new (zone) |
| 2888 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2847 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2889 summary->set_in(0, Location::RequiresRegister()); | 2848 summary->set_in(0, Location::RequiresRegister()); |
| 2890 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 2849 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 2891 if (kNumTemps == 1) { | 2850 if (kNumTemps == 1) { |
| 2892 summary->set_temp(0, Location::RequiresRegister()); | 2851 summary->set_temp(0, Location::RequiresRegister()); |
| 2893 } | 2852 } |
| 2894 summary->set_out(0, Location::SameAsFirstInput()); | 2853 summary->set_out(0, Location::SameAsFirstInput()); |
| 2895 return summary; | 2854 return summary; |
| 2896 } else { | 2855 } else { |
| 2897 const intptr_t kNumTemps = 0; | 2856 const intptr_t kNumTemps = 0; |
| 2898 LocationSummary* summary = new(zone) LocationSummary( | 2857 LocationSummary* summary = new (zone) |
| 2899 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2858 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2900 summary->set_in(0, Location::RequiresRegister()); | 2859 summary->set_in(0, Location::RequiresRegister()); |
| 2901 ConstantInstr* constant = right()->definition()->AsConstant(); | 2860 ConstantInstr* constant = right()->definition()->AsConstant(); |
| 2902 if (constant != NULL) { | 2861 if (constant != NULL) { |
| 2903 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 2862 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 2904 } else { | 2863 } else { |
| 2905 summary->set_in(1, Location::PrefersRegister()); | 2864 summary->set_in(1, Location::PrefersRegister()); |
| 2906 } | 2865 } |
| 2907 summary->set_out(0, Location::SameAsFirstInput()); | 2866 summary->set_out(0, Location::SameAsFirstInput()); |
| 2908 return summary; | 2867 return summary; |
| 2909 } | 2868 } |
| 2910 } | 2869 } |
| 2911 | 2870 |
| 2912 | 2871 |
| 2913 template<typename OperandType> | 2872 template <typename OperandType> |
| 2914 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, | 2873 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, |
| 2915 Token::Kind op_kind, | 2874 Token::Kind op_kind, |
| 2916 Register left, | 2875 Register left, |
| 2917 const OperandType& right, | 2876 const OperandType& right, |
| 2918 Label* deopt) { | 2877 Label* deopt) { |
| 2919 switch (op_kind) { | 2878 switch (op_kind) { |
| 2920 case Token::kADD: | 2879 case Token::kADD: |
| 2921 __ addl(left, right); | 2880 __ addl(left, right); |
| 2922 break; | 2881 break; |
| 2923 case Token::kSUB: | 2882 case Token::kSUB: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2960 const Object& constant = locs()->in(1).constant(); | 2919 const Object& constant = locs()->in(1).constant(); |
| 2961 ASSERT(constant.IsSmi()); | 2920 ASSERT(constant.IsSmi()); |
| 2962 const intptr_t value = Smi::Cast(constant).Value(); | 2921 const intptr_t value = Smi::Cast(constant).Value(); |
| 2963 switch (op_kind()) { | 2922 switch (op_kind()) { |
| 2964 case Token::kADD: | 2923 case Token::kADD: |
| 2965 case Token::kSUB: | 2924 case Token::kSUB: |
| 2966 case Token::kBIT_AND: | 2925 case Token::kBIT_AND: |
| 2967 case Token::kBIT_OR: | 2926 case Token::kBIT_OR: |
| 2968 case Token::kBIT_XOR: | 2927 case Token::kBIT_XOR: |
| 2969 case Token::kMUL: { | 2928 case Token::kMUL: { |
| 2970 const intptr_t imm = (op_kind() == Token::kMUL) ? value | 2929 const intptr_t imm = |
| 2971 : Smi::RawValue(value); | 2930 (op_kind() == Token::kMUL) ? value : Smi::RawValue(value); |
| 2972 EmitIntegerArithmetic(compiler, | 2931 EmitIntegerArithmetic(compiler, op_kind(), left, Immediate(imm), deopt); |
| 2973 op_kind(), | |
| 2974 left, | |
| 2975 Immediate(imm), | |
| 2976 deopt); | |
| 2977 break; | 2932 break; |
| 2978 } | 2933 } |
| 2979 | 2934 |
| 2980 case Token::kTRUNCDIV: { | 2935 case Token::kTRUNCDIV: { |
| 2981 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); | 2936 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); |
| 2982 const intptr_t shift_count = | 2937 const intptr_t shift_count = |
| 2983 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; | 2938 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; |
| 2984 ASSERT(kSmiTagSize == 1); | 2939 ASSERT(kSmiTagSize == 1); |
| 2985 Register temp = locs()->temp(0).reg(); | 2940 Register temp = locs()->temp(0).reg(); |
| 2986 __ movl(temp, left); | 2941 __ movl(temp, left); |
| 2987 __ sarl(temp, Immediate(31)); | 2942 __ sarl(temp, Immediate(31)); |
| 2988 ASSERT(shift_count > 1); // 1, -1 case handled above. | 2943 ASSERT(shift_count > 1); // 1, -1 case handled above. |
| 2989 __ shrl(temp, Immediate(32 - shift_count)); | 2944 __ shrl(temp, Immediate(32 - shift_count)); |
| 2990 __ addl(left, temp); | 2945 __ addl(left, temp); |
| 2991 ASSERT(shift_count > 0); | 2946 ASSERT(shift_count > 0); |
| 2992 __ sarl(left, Immediate(shift_count)); | 2947 __ sarl(left, Immediate(shift_count)); |
| 2993 if (value < 0) { | 2948 if (value < 0) { |
| 2994 __ negl(left); | 2949 __ negl(left); |
| 2995 } | 2950 } |
| 2996 __ SmiTag(left); | 2951 __ SmiTag(left); |
| 2997 break; | 2952 break; |
| 2998 } | 2953 } |
| 2999 | 2954 |
| 3000 case Token::kSHR: { | 2955 case Token::kSHR: { |
| 3001 // sarl operation masks the count to 5 bits. | 2956 // sarl operation masks the count to 5 bits. |
| 3002 const intptr_t kCountLimit = 0x1F; | 2957 const intptr_t kCountLimit = 0x1F; |
| 3003 __ sarl(left, Immediate( | 2958 __ sarl(left, |
| 3004 Utils::Minimum(value + kSmiTagSize, kCountLimit))); | 2959 Immediate(Utils::Minimum(value + kSmiTagSize, kCountLimit))); |
| 3005 __ SmiTag(left); | 2960 __ SmiTag(left); |
| 3006 break; | 2961 break; |
| 3007 } | 2962 } |
| 3008 | 2963 |
| 3009 default: | 2964 default: |
| 3010 UNREACHABLE(); | 2965 UNREACHABLE(); |
| 3011 break; | 2966 break; |
| 3012 } | 2967 } |
| 3013 return; | 2968 return; |
| 3014 } // if locs()->in(1).IsConstant() | 2969 } // if locs()->in(1).IsConstant() |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3044 // Handle divide by zero in runtime. | 2999 // Handle divide by zero in runtime. |
| 3045 __ testl(right, right); | 3000 __ testl(right, right); |
| 3046 __ j(ZERO, deopt); | 3001 __ j(ZERO, deopt); |
| 3047 } | 3002 } |
| 3048 ASSERT(left == EAX); | 3003 ASSERT(left == EAX); |
| 3049 ASSERT((right != EDX) && (right != EAX)); | 3004 ASSERT((right != EDX) && (right != EAX)); |
| 3050 ASSERT(locs()->temp(0).reg() == EDX); | 3005 ASSERT(locs()->temp(0).reg() == EDX); |
| 3051 ASSERT(result == EAX); | 3006 ASSERT(result == EAX); |
| 3052 __ SmiUntag(left); | 3007 __ SmiUntag(left); |
| 3053 __ SmiUntag(right); | 3008 __ SmiUntag(right); |
| 3054 __ cdq(); // Sign extend EAX -> EDX:EAX. | 3009 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 3055 __ idivl(right); // EAX: quotient, EDX: remainder. | 3010 __ idivl(right); // EAX: quotient, EDX: remainder. |
| 3056 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3011 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 3057 // case we cannot tag the result. | 3012 // case we cannot tag the result. |
| 3058 __ cmpl(result, Immediate(0x40000000)); | 3013 __ cmpl(result, Immediate(0x40000000)); |
| 3059 __ j(EQUAL, deopt); | 3014 __ j(EQUAL, deopt); |
| 3060 __ SmiTag(result); | 3015 __ SmiTag(result); |
| 3061 break; | 3016 break; |
| 3062 } | 3017 } |
| 3063 case Token::kMOD: { | 3018 case Token::kMOD: { |
| 3064 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3019 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 3065 // Handle divide by zero in runtime. | 3020 // Handle divide by zero in runtime. |
| 3066 __ testl(right, right); | 3021 __ testl(right, right); |
| 3067 __ j(ZERO, deopt); | 3022 __ j(ZERO, deopt); |
| 3068 } | 3023 } |
| 3069 ASSERT(left == EDX); | 3024 ASSERT(left == EDX); |
| 3070 ASSERT((right != EDX) && (right != EAX)); | 3025 ASSERT((right != EDX) && (right != EAX)); |
| 3071 ASSERT(locs()->temp(0).reg() == EAX); | 3026 ASSERT(locs()->temp(0).reg() == EAX); |
| 3072 ASSERT(result == EDX); | 3027 ASSERT(result == EDX); |
| 3073 __ SmiUntag(left); | 3028 __ SmiUntag(left); |
| 3074 __ SmiUntag(right); | 3029 __ SmiUntag(right); |
| 3075 __ movl(EAX, EDX); | 3030 __ movl(EAX, EDX); |
| 3076 __ cdq(); // Sign extend EAX -> EDX:EAX. | 3031 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 3077 __ idivl(right); // EAX: quotient, EDX: remainder. | 3032 __ idivl(right); // EAX: quotient, EDX: remainder. |
| 3078 // res = left % right; | 3033 // res = left % right; |
| 3079 // if (res < 0) { | 3034 // if (res < 0) { |
| 3080 // if (right < 0) { | 3035 // if (right < 0) { |
| 3081 // res = res - right; | 3036 // res = res - right; |
| 3082 // } else { | 3037 // } else { |
| 3083 // res = res + right; | 3038 // res = res + right; |
| 3084 // } | 3039 // } |
| 3085 // } | 3040 // } |
| 3086 Label done; | 3041 Label done; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3149 } | 3104 } |
| 3150 | 3105 |
| 3151 | 3106 |
| 3152 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, | 3107 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, |
| 3153 bool opt) const { | 3108 bool opt) const { |
| 3154 const intptr_t kNumInputs = 2; | 3109 const intptr_t kNumInputs = 2; |
| 3155 if (op_kind() == Token::kTRUNCDIV) { | 3110 if (op_kind() == Token::kTRUNCDIV) { |
| 3156 UNREACHABLE(); | 3111 UNREACHABLE(); |
| 3157 return NULL; | 3112 return NULL; |
| 3158 } else if (op_kind() == Token::kMOD) { | 3113 } else if (op_kind() == Token::kMOD) { |
| 3159 UNREACHABLE(); | 3114 UNREACHABLE(); |
| 3160 return NULL; | 3115 return NULL; |
| 3161 } else if (op_kind() == Token::kSHR) { | 3116 } else if (op_kind() == Token::kSHR) { |
| 3162 const intptr_t kNumTemps = 0; | 3117 const intptr_t kNumTemps = 0; |
| 3163 LocationSummary* summary = new(zone) LocationSummary( | 3118 LocationSummary* summary = new (zone) |
| 3164 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3119 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3165 summary->set_in(0, Location::RequiresRegister()); | 3120 summary->set_in(0, Location::RequiresRegister()); |
| 3166 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 3121 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 3167 summary->set_out(0, Location::SameAsFirstInput()); | 3122 summary->set_out(0, Location::SameAsFirstInput()); |
| 3168 return summary; | 3123 return summary; |
| 3169 } else if (op_kind() == Token::kSHL) { | 3124 } else if (op_kind() == Token::kSHL) { |
| 3170 const intptr_t kNumTemps = can_overflow() ? 1 : 0; | 3125 const intptr_t kNumTemps = can_overflow() ? 1 : 0; |
| 3171 LocationSummary* summary = new(zone) LocationSummary( | 3126 LocationSummary* summary = new (zone) |
| 3172 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3127 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3173 summary->set_in(0, Location::RequiresRegister()); | 3128 summary->set_in(0, Location::RequiresRegister()); |
| 3174 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 3129 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 3175 if (can_overflow()) { | 3130 if (can_overflow()) { |
| 3176 summary->set_temp(0, Location::RequiresRegister()); | 3131 summary->set_temp(0, Location::RequiresRegister()); |
| 3177 } | 3132 } |
| 3178 summary->set_out(0, Location::SameAsFirstInput()); | 3133 summary->set_out(0, Location::SameAsFirstInput()); |
| 3179 return summary; | 3134 return summary; |
| 3180 } else { | 3135 } else { |
| 3181 const intptr_t kNumTemps = 0; | 3136 const intptr_t kNumTemps = 0; |
| 3182 LocationSummary* summary = new(zone) LocationSummary( | 3137 LocationSummary* summary = new (zone) |
| 3183 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3138 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3184 summary->set_in(0, Location::RequiresRegister()); | 3139 summary->set_in(0, Location::RequiresRegister()); |
| 3185 ConstantInstr* constant = right()->definition()->AsConstant(); | 3140 ConstantInstr* constant = right()->definition()->AsConstant(); |
| 3186 if (constant != NULL) { | 3141 if (constant != NULL) { |
| 3187 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 3142 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 3188 } else { | 3143 } else { |
| 3189 summary->set_in(1, Location::PrefersRegister()); | 3144 summary->set_in(1, Location::PrefersRegister()); |
| 3190 } | 3145 } |
| 3191 summary->set_out(0, Location::SameAsFirstInput()); | 3146 summary->set_out(0, Location::SameAsFirstInput()); |
| 3192 return summary; | 3147 return summary; |
| 3193 } | 3148 } |
| 3194 } | 3149 } |
| 3195 | 3150 |
| 3196 | 3151 |
| 3197 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, | 3152 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, |
| 3198 BinaryInt32OpInstr* shift_left) { | 3153 BinaryInt32OpInstr* shift_left) { |
| 3199 const LocationSummary& locs = *shift_left->locs(); | 3154 const LocationSummary& locs = *shift_left->locs(); |
| 3200 Register left = locs.in(0).reg(); | 3155 Register left = locs.in(0).reg(); |
| 3201 Register result = locs.out(0).reg(); | 3156 Register result = locs.out(0).reg(); |
| 3202 ASSERT(left == result); | 3157 ASSERT(left == result); |
| 3203 Label* deopt = shift_left->CanDeoptimize() ? | 3158 Label* deopt = shift_left->CanDeoptimize() |
| 3204 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 3159 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 3205 : NULL; | 3160 ICData::kDeoptBinarySmiOp) |
| 3161 : NULL; |
| 3206 ASSERT(locs.in(1).IsConstant()); | 3162 ASSERT(locs.in(1).IsConstant()); |
| 3207 | 3163 |
| 3208 const Object& constant = locs.in(1).constant(); | 3164 const Object& constant = locs.in(1).constant(); |
| 3209 ASSERT(constant.IsSmi()); | 3165 ASSERT(constant.IsSmi()); |
| 3210 // shll operation masks the count to 5 bits. | 3166 // shll operation masks the count to 5 bits. |
| 3211 const intptr_t kCountLimit = 0x1F; | 3167 const intptr_t kCountLimit = 0x1F; |
| 3212 const intptr_t value = Smi::Cast(constant).Value(); | 3168 const intptr_t value = Smi::Cast(constant).Value(); |
| 3213 ASSERT((0 < value) && (value < kCountLimit)); | 3169 ASSERT((0 < value) && (value < kCountLimit)); |
| 3214 if (shift_left->can_overflow()) { | 3170 if (shift_left->can_overflow()) { |
| 3215 // Check for overflow. | 3171 // Check for overflow. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3229 if (op_kind() == Token::kSHL) { | 3185 if (op_kind() == Token::kSHL) { |
| 3230 EmitInt32ShiftLeft(compiler, this); | 3186 EmitInt32ShiftLeft(compiler, this); |
| 3231 return; | 3187 return; |
| 3232 } | 3188 } |
| 3233 | 3189 |
| 3234 Register left = locs()->in(0).reg(); | 3190 Register left = locs()->in(0).reg(); |
| 3235 Register result = locs()->out(0).reg(); | 3191 Register result = locs()->out(0).reg(); |
| 3236 ASSERT(left == result); | 3192 ASSERT(left == result); |
| 3237 Label* deopt = NULL; | 3193 Label* deopt = NULL; |
| 3238 if (CanDeoptimize()) { | 3194 if (CanDeoptimize()) { |
| 3239 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 3195 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
| 3240 } | 3196 } |
| 3241 | 3197 |
| 3242 if (locs()->in(1).IsConstant()) { | 3198 if (locs()->in(1).IsConstant()) { |
| 3243 const Object& constant = locs()->in(1).constant(); | 3199 const Object& constant = locs()->in(1).constant(); |
| 3244 ASSERT(constant.IsSmi()); | 3200 ASSERT(constant.IsSmi()); |
| 3245 const intptr_t value = Smi::Cast(constant).Value(); | 3201 const intptr_t value = Smi::Cast(constant).Value(); |
| 3246 switch (op_kind()) { | 3202 switch (op_kind()) { |
| 3247 case Token::kADD: | 3203 case Token::kADD: |
| 3248 case Token::kSUB: | 3204 case Token::kSUB: |
| 3249 case Token::kMUL: | 3205 case Token::kMUL: |
| 3250 case Token::kBIT_AND: | 3206 case Token::kBIT_AND: |
| 3251 case Token::kBIT_OR: | 3207 case Token::kBIT_OR: |
| 3252 case Token::kBIT_XOR: | 3208 case Token::kBIT_XOR: |
| 3253 EmitIntegerArithmetic(compiler, | 3209 EmitIntegerArithmetic(compiler, op_kind(), left, Immediate(value), |
| 3254 op_kind(), | |
| 3255 left, | |
| 3256 Immediate(value), | |
| 3257 deopt); | 3210 deopt); |
| 3258 break; | 3211 break; |
| 3259 | 3212 |
| 3260 | 3213 |
| 3261 | |
| 3262 case Token::kTRUNCDIV: { | 3214 case Token::kTRUNCDIV: { |
| 3263 UNREACHABLE(); | 3215 UNREACHABLE(); |
| 3264 break; | 3216 break; |
| 3265 } | 3217 } |
| 3266 | 3218 |
| 3267 case Token::kSHR: { | 3219 case Token::kSHR: { |
| 3268 // sarl operation masks the count to 5 bits. | 3220 // sarl operation masks the count to 5 bits. |
| 3269 const intptr_t kCountLimit = 0x1F; | 3221 const intptr_t kCountLimit = 0x1F; |
| 3270 __ sarl(left, Immediate(Utils::Minimum(value, kCountLimit))); | 3222 __ sarl(left, Immediate(Utils::Minimum(value, kCountLimit))); |
| 3271 break; | 3223 break; |
| 3272 } | 3224 } |
| 3273 | 3225 |
| 3274 default: | 3226 default: |
| 3275 UNREACHABLE(); | 3227 UNREACHABLE(); |
| 3276 break; | 3228 break; |
| 3277 } | 3229 } |
| 3278 return; | 3230 return; |
| 3279 } // if locs()->in(1).IsConstant() | 3231 } // if locs()->in(1).IsConstant() |
| 3280 | 3232 |
| 3281 if (locs()->in(1).IsStackSlot()) { | 3233 if (locs()->in(1).IsStackSlot()) { |
| 3282 const Address& right = locs()->in(1).ToStackSlotAddress(); | 3234 const Address& right = locs()->in(1).ToStackSlotAddress(); |
| 3283 EmitIntegerArithmetic(compiler, | 3235 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); |
| 3284 op_kind(), | |
| 3285 left, | |
| 3286 right, | |
| 3287 deopt); | |
| 3288 return; | 3236 return; |
| 3289 } // if locs()->in(1).IsStackSlot. | 3237 } // if locs()->in(1).IsStackSlot. |
| 3290 | 3238 |
| 3291 // if locs()->in(1).IsRegister. | 3239 // if locs()->in(1).IsRegister. |
| 3292 Register right = locs()->in(1).reg(); | 3240 Register right = locs()->in(1).reg(); |
| 3293 switch (op_kind()) { | 3241 switch (op_kind()) { |
| 3294 case Token::kADD: | 3242 case Token::kADD: |
| 3295 case Token::kSUB: | 3243 case Token::kSUB: |
| 3296 case Token::kMUL: | 3244 case Token::kMUL: |
| 3297 case Token::kBIT_AND: | 3245 case Token::kBIT_AND: |
| 3298 case Token::kBIT_OR: | 3246 case Token::kBIT_OR: |
| 3299 case Token::kBIT_XOR: | 3247 case Token::kBIT_XOR: |
| 3300 EmitIntegerArithmetic(compiler, | 3248 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); |
| 3301 op_kind(), | |
| 3302 left, | |
| 3303 right, | |
| 3304 deopt); | |
| 3305 break; | 3249 break; |
| 3306 | 3250 |
| 3307 default: | 3251 default: |
| 3308 UNREACHABLE(); | 3252 UNREACHABLE(); |
| 3309 break; | 3253 break; |
| 3310 } | 3254 } |
| 3311 } | 3255 } |
| 3312 | 3256 |
| 3313 | 3257 |
| 3314 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 3258 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 3315 bool opt) const { | 3259 bool opt) const { |
| 3316 const intptr_t kNumInputs = 2; | 3260 const intptr_t kNumInputs = 2; |
| 3317 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; | 3261 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
| 3318 LocationSummary* summary = new(zone) LocationSummary( | 3262 LocationSummary* summary = new (zone) |
| 3319 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3263 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3320 if (op_kind() == Token::kMUL) { | 3264 if (op_kind() == Token::kMUL) { |
| 3321 summary->set_in(0, Location::RegisterLocation(EAX)); | 3265 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 3322 summary->set_temp(0, Location::RegisterLocation(EDX)); | 3266 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 3323 } else { | 3267 } else { |
| 3324 summary->set_in(0, Location::RequiresRegister()); | 3268 summary->set_in(0, Location::RequiresRegister()); |
| 3325 } | 3269 } |
| 3326 summary->set_in(1, Location::RequiresRegister()); | 3270 summary->set_in(1, Location::RequiresRegister()); |
| 3327 summary->set_out(0, Location::SameAsFirstInput()); | 3271 summary->set_out(0, Location::SameAsFirstInput()); |
| 3328 return summary; | 3272 return summary; |
| 3329 } | 3273 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3353 } | 3297 } |
| 3354 } | 3298 } |
| 3355 | 3299 |
| 3356 | 3300 |
| 3357 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3301 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
| 3358 bool opt) const { | 3302 bool opt) const { |
| 3359 intptr_t left_cid = left()->Type()->ToCid(); | 3303 intptr_t left_cid = left()->Type()->ToCid(); |
| 3360 intptr_t right_cid = right()->Type()->ToCid(); | 3304 intptr_t right_cid = right()->Type()->ToCid(); |
| 3361 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3305 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
| 3362 const intptr_t kNumInputs = 2; | 3306 const intptr_t kNumInputs = 2; |
| 3363 const bool need_temp = (left()->definition() != right()->definition()) | 3307 const bool need_temp = (left()->definition() != right()->definition()) && |
| 3364 && (left_cid != kSmiCid) | 3308 (left_cid != kSmiCid) && (right_cid != kSmiCid); |
| 3365 && (right_cid != kSmiCid); | |
| 3366 const intptr_t kNumTemps = need_temp ? 1 : 0; | 3309 const intptr_t kNumTemps = need_temp ? 1 : 0; |
| 3367 LocationSummary* summary = new(zone) LocationSummary( | 3310 LocationSummary* summary = new (zone) |
| 3368 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3311 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3369 summary->set_in(0, Location::RequiresRegister()); | 3312 summary->set_in(0, Location::RequiresRegister()); |
| 3370 summary->set_in(1, Location::RequiresRegister()); | 3313 summary->set_in(1, Location::RequiresRegister()); |
| 3371 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); | 3314 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); |
| 3372 return summary; | 3315 return summary; |
| 3373 } | 3316 } |
| 3374 | 3317 |
| 3375 | 3318 |
| 3376 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3319 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3377 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3320 Label* deopt = |
| 3378 ICData::kDeoptBinaryDoubleOp, | 3321 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
| 3379 licm_hoisted_ ? ICData::kHoisted : 0); | 3322 licm_hoisted_ ? ICData::kHoisted : 0); |
| 3380 intptr_t left_cid = left()->Type()->ToCid(); | 3323 intptr_t left_cid = left()->Type()->ToCid(); |
| 3381 intptr_t right_cid = right()->Type()->ToCid(); | 3324 intptr_t right_cid = right()->Type()->ToCid(); |
| 3382 Register left = locs()->in(0).reg(); | 3325 Register left = locs()->in(0).reg(); |
| 3383 Register right = locs()->in(1).reg(); | 3326 Register right = locs()->in(1).reg(); |
| 3384 if (this->left()->definition() == this->right()->definition()) { | 3327 if (this->left()->definition() == this->right()->definition()) { |
| 3385 __ testl(left, Immediate(kSmiTagMask)); | 3328 __ testl(left, Immediate(kSmiTagMask)); |
| 3386 } else if (left_cid == kSmiCid) { | 3329 } else if (left_cid == kSmiCid) { |
| 3387 __ testl(right, Immediate(kSmiTagMask)); | 3330 __ testl(right, Immediate(kSmiTagMask)); |
| 3388 } else if (right_cid == kSmiCid) { | 3331 } else if (right_cid == kSmiCid) { |
| 3389 __ testl(left, Immediate(kSmiTagMask)); | 3332 __ testl(left, Immediate(kSmiTagMask)); |
| 3390 } else { | 3333 } else { |
| 3391 Register temp = locs()->temp(0).reg(); | 3334 Register temp = locs()->temp(0).reg(); |
| 3392 __ movl(temp, left); | 3335 __ movl(temp, left); |
| 3393 __ orl(temp, right); | 3336 __ orl(temp, right); |
| 3394 __ testl(temp, Immediate(kSmiTagMask)); | 3337 __ testl(temp, Immediate(kSmiTagMask)); |
| 3395 } | 3338 } |
| 3396 __ j(ZERO, deopt); | 3339 __ j(ZERO, deopt); |
| 3397 } | 3340 } |
| 3398 | 3341 |
| 3399 | 3342 |
| 3400 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, | 3343 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3401 bool opt) const { | |
| 3402 const intptr_t kNumInputs = 1; | 3344 const intptr_t kNumInputs = 1; |
| 3403 const intptr_t kNumTemps = 1; | 3345 const intptr_t kNumTemps = 1; |
| 3404 LocationSummary* summary = new(zone) LocationSummary( | 3346 LocationSummary* summary = new (zone) LocationSummary( |
| 3405 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3347 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3406 summary->set_in(0, Location::RequiresFpuRegister()); | 3348 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3407 summary->set_temp(0, Location::RequiresRegister()); | 3349 summary->set_temp(0, Location::RequiresRegister()); |
| 3408 summary->set_out(0, Location::RequiresRegister()); | 3350 summary->set_out(0, Location::RequiresRegister()); |
| 3409 return summary; | 3351 return summary; |
| 3410 } | 3352 } |
| 3411 | 3353 |
| 3412 | 3354 |
| 3413 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3355 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3414 Register out_reg = locs()->out(0).reg(); | 3356 Register out_reg = locs()->out(0).reg(); |
| 3415 XmmRegister value = locs()->in(0).fpu_reg(); | 3357 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3416 | 3358 |
| 3417 BoxAllocationSlowPath::Allocate( | 3359 BoxAllocationSlowPath::Allocate(compiler, this, |
| 3418 compiler, | 3360 compiler->BoxClassFor(from_representation()), |
| 3419 this, | 3361 out_reg, locs()->temp(0).reg()); |
| 3420 compiler->BoxClassFor(from_representation()), | |
| 3421 out_reg, | |
| 3422 locs()->temp(0).reg()); | |
| 3423 | 3362 |
| 3424 switch (from_representation()) { | 3363 switch (from_representation()) { |
| 3425 case kUnboxedDouble: | 3364 case kUnboxedDouble: |
| 3426 __ movsd(FieldAddress(out_reg, ValueOffset()), value); | 3365 __ movsd(FieldAddress(out_reg, ValueOffset()), value); |
| 3427 break; | 3366 break; |
| 3428 case kUnboxedFloat32x4: | 3367 case kUnboxedFloat32x4: |
| 3429 case kUnboxedFloat64x2: | 3368 case kUnboxedFloat64x2: |
| 3430 case kUnboxedInt32x4: | 3369 case kUnboxedInt32x4: |
| 3431 __ movups(FieldAddress(out_reg, ValueOffset()), value); | 3370 __ movups(FieldAddress(out_reg, ValueOffset()), value); |
| 3432 break; | 3371 break; |
| 3433 default: | 3372 default: |
| 3434 UNREACHABLE(); | 3373 UNREACHABLE(); |
| 3435 break; | 3374 break; |
| 3436 } | 3375 } |
| 3437 } | 3376 } |
| 3438 | 3377 |
| 3439 | 3378 |
| 3440 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, | 3379 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3441 bool opt) const { | 3380 const bool needs_temp = |
| 3442 const bool needs_temp = CanDeoptimize() || | 3381 CanDeoptimize() || |
| 3443 (CanConvertSmi() && (value()->Type()->ToCid() == kSmiCid)); | 3382 (CanConvertSmi() && (value()->Type()->ToCid() == kSmiCid)); |
| 3444 | 3383 |
| 3445 const intptr_t kNumInputs = 1; | 3384 const intptr_t kNumInputs = 1; |
| 3446 const intptr_t kNumTemps = needs_temp ? 1 : 0; | 3385 const intptr_t kNumTemps = needs_temp ? 1 : 0; |
| 3447 LocationSummary* summary = new(zone) LocationSummary( | 3386 LocationSummary* summary = new (zone) |
| 3448 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3387 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3449 summary->set_in(0, Location::RequiresRegister()); | 3388 summary->set_in(0, Location::RequiresRegister()); |
| 3450 if (needs_temp) { | 3389 if (needs_temp) { |
| 3451 summary->set_temp(0, Location::RequiresRegister()); | 3390 summary->set_temp(0, Location::RequiresRegister()); |
| 3452 } | 3391 } |
| 3453 if (representation() == kUnboxedMint) { | 3392 if (representation() == kUnboxedMint) { |
| 3454 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 3393 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
| 3455 Location::RegisterLocation(EDX))); | 3394 Location::RegisterLocation(EDX))); |
| 3456 } else { | 3395 } else { |
| 3457 summary->set_out(0, Location::RequiresFpuRegister()); | 3396 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3458 } | 3397 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3527 const intptr_t value_cid = value()->Type()->ToCid(); | 3466 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3528 const intptr_t box_cid = BoxCid(); | 3467 const intptr_t box_cid = BoxCid(); |
| 3529 | 3468 |
| 3530 if (value_cid == box_cid) { | 3469 if (value_cid == box_cid) { |
| 3531 EmitLoadFromBox(compiler); | 3470 EmitLoadFromBox(compiler); |
| 3532 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3471 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
| 3533 EmitSmiConversion(compiler); | 3472 EmitSmiConversion(compiler); |
| 3534 } else { | 3473 } else { |
| 3535 const Register box = locs()->in(0).reg(); | 3474 const Register box = locs()->in(0).reg(); |
| 3536 const Register temp = locs()->temp(0).reg(); | 3475 const Register temp = locs()->temp(0).reg(); |
| 3537 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 3476 Label* deopt = |
| 3538 ICData::kDeoptCheckClass); | 3477 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); |
| 3539 Label is_smi; | 3478 Label is_smi; |
| 3540 | 3479 |
| 3541 if ((value()->Type()->ToNullableCid() == box_cid) && | 3480 if ((value()->Type()->ToNullableCid() == box_cid) && |
| 3542 value()->Type()->is_nullable()) { | 3481 value()->Type()->is_nullable()) { |
| 3543 const Immediate& raw_null = | 3482 const Immediate& raw_null = |
| 3544 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 3483 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 3545 __ cmpl(box, raw_null); | 3484 __ cmpl(box, raw_null); |
| 3546 __ j(EQUAL, deopt); | 3485 __ j(EQUAL, deopt); |
| 3547 } else { | 3486 } else { |
| 3548 __ testl(box, Immediate(kSmiTagMask)); | 3487 __ testl(box, Immediate(kSmiTagMask)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3561 __ Bind(&done); | 3500 __ Bind(&done); |
| 3562 } | 3501 } |
| 3563 } | 3502 } |
| 3564 } | 3503 } |
| 3565 | 3504 |
| 3566 | 3505 |
| 3567 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3506 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3568 bool opt) const { | 3507 bool opt) const { |
| 3569 const intptr_t kNumInputs = 1; | 3508 const intptr_t kNumInputs = 1; |
| 3570 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3509 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 3571 LocationSummary* summary = new(zone) LocationSummary( | 3510 LocationSummary* summary = new (zone) |
| 3572 zone, kNumInputs, kNumTemps, | 3511 LocationSummary(zone, kNumInputs, kNumTemps, |
| 3573 ValueFitsSmi() ? LocationSummary::kNoCall | 3512 ValueFitsSmi() ? LocationSummary::kNoCall |
| 3574 : LocationSummary::kCallOnSlowPath); | 3513 : LocationSummary::kCallOnSlowPath); |
| 3575 const bool needs_writable_input = ValueFitsSmi() || | 3514 const bool needs_writable_input = |
| 3576 (from_representation() == kUnboxedUint32); | 3515 ValueFitsSmi() || (from_representation() == kUnboxedUint32); |
| 3577 summary->set_in(0, needs_writable_input ? Location::RequiresRegister() | 3516 summary->set_in(0, needs_writable_input ? Location::RequiresRegister() |
| 3578 : Location::WritableRegister()); | 3517 : Location::WritableRegister()); |
| 3579 if (!ValueFitsSmi()) { | 3518 if (!ValueFitsSmi()) { |
| 3580 summary->set_temp(0, Location::RequiresRegister()); | 3519 summary->set_temp(0, Location::RequiresRegister()); |
| 3581 } | 3520 } |
| 3582 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() | 3521 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() |
| 3583 : Location::RequiresRegister()); | 3522 : Location::RequiresRegister()); |
| 3584 return summary; | 3523 return summary; |
| 3585 } | 3524 } |
| 3586 | 3525 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3598 __ j(NO_OVERFLOW, &done); | 3537 __ j(NO_OVERFLOW, &done); |
| 3599 } else { | 3538 } else { |
| 3600 __ testl(value, Immediate(0xC0000000)); | 3539 __ testl(value, Immediate(0xC0000000)); |
| 3601 __ j(ZERO, &done); | 3540 __ j(ZERO, &done); |
| 3602 } | 3541 } |
| 3603 | 3542 |
| 3604 // Allocate a mint. | 3543 // Allocate a mint. |
| 3605 // Value input is writable register and has to be manually preserved | 3544 // Value input is writable register and has to be manually preserved |
| 3606 // on the slow path. | 3545 // on the slow path. |
| 3607 locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32); | 3546 locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32); |
| 3608 BoxAllocationSlowPath::Allocate( | 3547 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, |
| 3609 compiler, this, compiler->mint_class(), out, locs()->temp(0).reg()); | 3548 locs()->temp(0).reg()); |
| 3610 __ movl(FieldAddress(out, Mint::value_offset()), value); | 3549 __ movl(FieldAddress(out, Mint::value_offset()), value); |
| 3611 if (from_representation() == kUnboxedInt32) { | 3550 if (from_representation() == kUnboxedInt32) { |
| 3612 __ sarl(value, Immediate(31)); // Sign extend. | 3551 __ sarl(value, Immediate(31)); // Sign extend. |
| 3613 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value); | 3552 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value); |
| 3614 } else { | 3553 } else { |
| 3615 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), | 3554 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), |
| 3616 Immediate(0)); | 3555 Immediate(0)); |
| 3617 } | 3556 } |
| 3618 __ Bind(&done); | 3557 __ Bind(&done); |
| 3619 } | 3558 } |
| 3620 } | 3559 } |
| 3621 | 3560 |
| 3622 | 3561 |
| 3623 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 3562 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
| 3624 bool opt) const { | 3563 bool opt) const { |
| 3625 const intptr_t kNumInputs = 1; | 3564 const intptr_t kNumInputs = 1; |
| 3626 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3565 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 3627 LocationSummary* summary = new(zone) LocationSummary( | 3566 LocationSummary* summary = new (zone) |
| 3628 zone, kNumInputs, | 3567 LocationSummary(zone, kNumInputs, kNumTemps, |
| 3629 kNumTemps, | 3568 ValueFitsSmi() ? LocationSummary::kNoCall |
| 3630 ValueFitsSmi() | 3569 : LocationSummary::kCallOnSlowPath); |
| 3631 ? LocationSummary::kNoCall | |
| 3632 : LocationSummary::kCallOnSlowPath); | |
| 3633 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 3570 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 3634 Location::RequiresRegister())); | 3571 Location::RequiresRegister())); |
| 3635 if (!ValueFitsSmi()) { | 3572 if (!ValueFitsSmi()) { |
| 3636 summary->set_temp(0, Location::RequiresRegister()); | 3573 summary->set_temp(0, Location::RequiresRegister()); |
| 3637 } | 3574 } |
| 3638 summary->set_out(0, Location::RequiresRegister()); | 3575 summary->set_out(0, Location::RequiresRegister()); |
| 3639 return summary; | 3576 return summary; |
| 3640 } | 3577 } |
| 3641 | 3578 |
| 3642 | 3579 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3673 __ j(ABOVE_EQUAL, ¬_smi); | 3610 __ j(ABOVE_EQUAL, ¬_smi); |
| 3674 // 3. Restore lower half if result is a smi. | 3611 // 3. Restore lower half if result is a smi. |
| 3675 __ subl(value_lo, Immediate(0x40000000)); | 3612 __ subl(value_lo, Immediate(0x40000000)); |
| 3676 __ movl(out_reg, value_lo); | 3613 __ movl(out_reg, value_lo); |
| 3677 __ SmiTag(out_reg); | 3614 __ SmiTag(out_reg); |
| 3678 __ jmp(&done); | 3615 __ jmp(&done); |
| 3679 __ Bind(¬_smi); | 3616 __ Bind(¬_smi); |
| 3680 // 3. Restore lower half of input before using it. | 3617 // 3. Restore lower half of input before using it. |
| 3681 __ subl(value_lo, Immediate(0x40000000)); | 3618 __ subl(value_lo, Immediate(0x40000000)); |
| 3682 | 3619 |
| 3683 BoxAllocationSlowPath::Allocate( | 3620 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
| 3684 compiler, this, compiler->mint_class(), out_reg, locs()->temp(0).reg()); | 3621 out_reg, locs()->temp(0).reg()); |
| 3685 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo); | 3622 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo); |
| 3686 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi); | 3623 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi); |
| 3687 __ Bind(&done); | 3624 __ Bind(&done); |
| 3688 } | 3625 } |
| 3689 | 3626 |
| 3690 | 3627 |
| 3691 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3628 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3692 bool opt) const { | 3629 bool opt) const { |
| 3693 const intptr_t value_cid = value()->Type()->ToCid(); | 3630 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3694 const intptr_t kNumInputs = 1; | 3631 const intptr_t kNumInputs = 1; |
| 3695 intptr_t kNumTemps = 0; | 3632 intptr_t kNumTemps = 0; |
| 3696 | 3633 |
| 3697 if (CanDeoptimize()) { | 3634 if (CanDeoptimize()) { |
| 3698 if ((value_cid != kSmiCid) && | 3635 if ((value_cid != kSmiCid) && (value_cid != kMintCid) && !is_truncating()) { |
| 3699 (value_cid != kMintCid) && | |
| 3700 !is_truncating()) { | |
| 3701 kNumTemps = 2; | 3636 kNumTemps = 2; |
| 3702 } else { | 3637 } else { |
| 3703 kNumTemps = 1; | 3638 kNumTemps = 1; |
| 3704 } | 3639 } |
| 3705 } | 3640 } |
| 3706 | 3641 |
| 3707 LocationSummary* summary = new(zone) LocationSummary( | 3642 LocationSummary* summary = new (zone) |
| 3708 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3643 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3709 summary->set_in(0, Location::RequiresRegister()); | 3644 summary->set_in(0, Location::RequiresRegister()); |
| 3710 for (int i = 0; i < kNumTemps; i++) { | 3645 for (int i = 0; i < kNumTemps; i++) { |
| 3711 summary->set_temp(i, Location::RequiresRegister()); | 3646 summary->set_temp(i, Location::RequiresRegister()); |
| 3712 } | 3647 } |
| 3713 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid)) ? | 3648 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid)) |
| 3714 Location::SameAsFirstInput() : Location::RequiresRegister()); | 3649 ? Location::SameAsFirstInput() |
| 3650 : Location::RequiresRegister()); |
| 3715 return summary; | 3651 return summary; |
| 3716 } | 3652 } |
| 3717 | 3653 |
| 3718 | 3654 |
| 3719 static void LoadInt32FromMint(FlowGraphCompiler* compiler, | 3655 static void LoadInt32FromMint(FlowGraphCompiler* compiler, |
| 3720 Register result, | 3656 Register result, |
| 3721 const Address& lo, | 3657 const Address& lo, |
| 3722 const Address& hi, | 3658 const Address& hi, |
| 3723 Register temp, | 3659 Register temp, |
| 3724 Label* deopt) { | 3660 Label* deopt) { |
| 3725 __ movl(result, lo); | 3661 __ movl(result, lo); |
| 3726 if (deopt != NULL) { | 3662 if (deopt != NULL) { |
| 3727 ASSERT(temp != result); | 3663 ASSERT(temp != result); |
| 3728 __ movl(temp, result); | 3664 __ movl(temp, result); |
| 3729 __ sarl(temp, Immediate(31)); | 3665 __ sarl(temp, Immediate(31)); |
| 3730 __ cmpl(temp, hi); | 3666 __ cmpl(temp, hi); |
| 3731 __ j(NOT_EQUAL, deopt); | 3667 __ j(NOT_EQUAL, deopt); |
| 3732 } | 3668 } |
| 3733 } | 3669 } |
| 3734 | 3670 |
| 3735 | 3671 |
| 3736 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3672 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3737 const intptr_t value_cid = value()->Type()->ToCid(); | 3673 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3738 Register value = locs()->in(0).reg(); | 3674 Register value = locs()->in(0).reg(); |
| 3739 const Register result = locs()->out(0).reg(); | 3675 const Register result = locs()->out(0).reg(); |
| 3740 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; | 3676 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; |
| 3741 Label* deopt = CanDeoptimize() ? | 3677 Label* deopt = |
| 3742 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; | 3678 CanDeoptimize() |
| 3679 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 3680 : NULL; |
| 3743 Label* out_of_range = !is_truncating() ? deopt : NULL; | 3681 Label* out_of_range = !is_truncating() ? deopt : NULL; |
| 3744 | 3682 |
| 3745 const intptr_t lo_offset = Mint::value_offset(); | 3683 const intptr_t lo_offset = Mint::value_offset(); |
| 3746 const intptr_t hi_offset = Mint::value_offset() + kWordSize; | 3684 const intptr_t hi_offset = Mint::value_offset() + kWordSize; |
| 3747 | 3685 |
| 3748 if (value_cid == kSmiCid) { | 3686 if (value_cid == kSmiCid) { |
| 3749 ASSERT(value == result); | 3687 ASSERT(value == result); |
| 3750 __ SmiUntag(value); | 3688 __ SmiUntag(value); |
| 3751 } else if (value_cid == kMintCid) { | 3689 } else if (value_cid == kMintCid) { |
| 3752 ASSERT((value != result) || (out_of_range == NULL)); | 3690 ASSERT((value != result) || (out_of_range == NULL)); |
| 3753 LoadInt32FromMint(compiler, | 3691 LoadInt32FromMint(compiler, result, FieldAddress(value, lo_offset), |
| 3754 result, | 3692 FieldAddress(value, hi_offset), temp, out_of_range); |
| 3755 FieldAddress(value, lo_offset), | |
| 3756 FieldAddress(value, hi_offset), | |
| 3757 temp, | |
| 3758 out_of_range); | |
| 3759 } else if (!CanDeoptimize()) { | 3693 } else if (!CanDeoptimize()) { |
| 3760 ASSERT(value == result); | 3694 ASSERT(value == result); |
| 3761 Label done; | 3695 Label done; |
| 3762 __ SmiUntag(value); | 3696 __ SmiUntag(value); |
| 3763 __ j(NOT_CARRY, &done); | 3697 __ j(NOT_CARRY, &done); |
| 3764 __ movl(value, Address(value, TIMES_2, lo_offset)); | 3698 __ movl(value, Address(value, TIMES_2, lo_offset)); |
| 3765 __ Bind(&done); | 3699 __ Bind(&done); |
| 3766 } else { | 3700 } else { |
| 3767 ASSERT(value == result); | 3701 ASSERT(value == result); |
| 3768 Label done; | 3702 Label done; |
| 3769 __ SmiUntagOrCheckClass(value, kMintCid, temp, &done); | 3703 __ SmiUntagOrCheckClass(value, kMintCid, temp, &done); |
| 3770 __ j(NOT_EQUAL, deopt); | 3704 __ j(NOT_EQUAL, deopt); |
| 3771 if (out_of_range != NULL) { | 3705 if (out_of_range != NULL) { |
| 3772 Register value_temp = locs()->temp(1).reg(); | 3706 Register value_temp = locs()->temp(1).reg(); |
| 3773 __ movl(value_temp, value); | 3707 __ movl(value_temp, value); |
| 3774 value = value_temp; | 3708 value = value_temp; |
| 3775 } | 3709 } |
| 3776 LoadInt32FromMint(compiler, | 3710 LoadInt32FromMint(compiler, result, Address(value, TIMES_2, lo_offset), |
| 3777 result, | 3711 Address(value, TIMES_2, hi_offset), temp, out_of_range); |
| 3778 Address(value, TIMES_2, lo_offset), | |
| 3779 Address(value, TIMES_2, hi_offset), | |
| 3780 temp, | |
| 3781 out_of_range); | |
| 3782 __ Bind(&done); | 3712 __ Bind(&done); |
| 3783 } | 3713 } |
| 3784 } | 3714 } |
| 3785 | 3715 |
| 3786 | 3716 |
| 3787 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 3717 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
| 3788 bool opt) const { | 3718 bool opt) const { |
| 3789 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); | 3719 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); |
| 3790 const intptr_t kNumInputs = 2; | 3720 const intptr_t kNumInputs = 2; |
| 3791 const intptr_t kNumTemps = might_box ? 2 : 0; | 3721 const intptr_t kNumTemps = might_box ? 2 : 0; |
| 3792 LocationSummary* summary = new(zone) LocationSummary( | 3722 LocationSummary* summary = new (zone) LocationSummary( |
| 3793 zone, kNumInputs, kNumTemps, | 3723 zone, kNumInputs, kNumTemps, |
| 3794 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); | 3724 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); |
| 3795 summary->set_in(0, Location::RequiresRegister()); | 3725 summary->set_in(0, Location::RequiresRegister()); |
| 3796 // The smi index is either untagged (element size == 1), or it is left smi | 3726 // The smi index is either untagged (element size == 1), or it is left smi |
| 3797 // tagged (for all element sizes > 1). | 3727 // tagged (for all element sizes > 1). |
| 3798 summary->set_in(1, (index_scale() == 1) ? Location::WritableRegister() | 3728 summary->set_in(1, (index_scale() == 1) ? Location::WritableRegister() |
| 3799 : Location::RequiresRegister()); | 3729 : Location::RequiresRegister()); |
| 3800 if (might_box) { | 3730 if (might_box) { |
| 3801 summary->set_temp(0, Location::RequiresRegister()); | 3731 summary->set_temp(0, Location::RequiresRegister()); |
| 3802 summary->set_temp(1, Location::RequiresRegister()); | 3732 summary->set_temp(1, Location::RequiresRegister()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3813 return summary; | 3743 return summary; |
| 3814 } | 3744 } |
| 3815 | 3745 |
| 3816 | 3746 |
| 3817 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3747 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3818 // The string register points to the backing store for external strings. | 3748 // The string register points to the backing store for external strings. |
| 3819 const Register str = locs()->in(0).reg(); | 3749 const Register str = locs()->in(0).reg(); |
| 3820 const Location index = locs()->in(1); | 3750 const Location index = locs()->in(1); |
| 3821 | 3751 |
| 3822 Address element_address = Assembler::ElementAddressForRegIndex( | 3752 Address element_address = Assembler::ElementAddressForRegIndex( |
| 3823 IsExternal(), class_id(), index_scale(), str, index.reg()); | 3753 IsExternal(), class_id(), index_scale(), str, index.reg()); |
| 3824 | 3754 |
| 3825 if ((index_scale() == 1)) { | 3755 if ((index_scale() == 1)) { |
| 3826 __ SmiUntag(index.reg()); | 3756 __ SmiUntag(index.reg()); |
| 3827 } | 3757 } |
| 3828 | 3758 |
| 3829 if (representation() == kUnboxedMint) { | 3759 if (representation() == kUnboxedMint) { |
| 3830 ASSERT(compiler->is_optimizing()); | 3760 ASSERT(compiler->is_optimizing()); |
| 3831 ASSERT(locs()->out(0).IsPairLocation()); | 3761 ASSERT(locs()->out(0).IsPairLocation()); |
| 3832 PairLocation* result_pair = locs()->out(0).AsPairLocation(); | 3762 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
| 3833 Register result1 = result_pair->At(0).reg(); | 3763 Register result1 = result_pair->At(0).reg(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3849 default: | 3779 default: |
| 3850 UNREACHABLE(); | 3780 UNREACHABLE(); |
| 3851 } | 3781 } |
| 3852 } else { | 3782 } else { |
| 3853 ASSERT(representation() == kTagged); | 3783 ASSERT(representation() == kTagged); |
| 3854 Register result = locs()->out(0).reg(); | 3784 Register result = locs()->out(0).reg(); |
| 3855 switch (class_id()) { | 3785 switch (class_id()) { |
| 3856 case kOneByteStringCid: | 3786 case kOneByteStringCid: |
| 3857 case kExternalOneByteStringCid: | 3787 case kExternalOneByteStringCid: |
| 3858 switch (element_count()) { | 3788 switch (element_count()) { |
| 3859 case 1: __ movzxb(result, element_address); break; | 3789 case 1: |
| 3860 case 2: __ movzxw(result, element_address); break; | 3790 __ movzxb(result, element_address); |
| 3861 case 4: __ movl(result, element_address); break; | 3791 break; |
| 3862 default: UNREACHABLE(); | 3792 case 2: |
| 3793 __ movzxw(result, element_address); |
| 3794 break; |
| 3795 case 4: |
| 3796 __ movl(result, element_address); |
| 3797 break; |
| 3798 default: |
| 3799 UNREACHABLE(); |
| 3863 } | 3800 } |
| 3864 break; | 3801 break; |
| 3865 case kTwoByteStringCid: | 3802 case kTwoByteStringCid: |
| 3866 case kExternalTwoByteStringCid: | 3803 case kExternalTwoByteStringCid: |
| 3867 switch (element_count()) { | 3804 switch (element_count()) { |
| 3868 case 1: __ movzxw(result, element_address); break; | 3805 case 1: |
| 3869 case 2: __ movl(result, element_address); break; | 3806 __ movzxw(result, element_address); |
| 3870 default: UNREACHABLE(); | 3807 break; |
| 3808 case 2: |
| 3809 __ movl(result, element_address); |
| 3810 break; |
| 3811 default: |
| 3812 UNREACHABLE(); |
| 3871 } | 3813 } |
| 3872 break; | 3814 break; |
| 3873 default: | 3815 default: |
| 3874 UNREACHABLE(); | 3816 UNREACHABLE(); |
| 3875 break; | 3817 break; |
| 3876 } | 3818 } |
| 3877 if (can_pack_into_smi()) { | 3819 if (can_pack_into_smi()) { |
| 3878 __ SmiTag(result); | 3820 __ SmiTag(result); |
| 3879 } else { | 3821 } else { |
| 3880 // If the value cannot fit in a smi then allocate a mint box for it. | 3822 // If the value cannot fit in a smi then allocate a mint box for it. |
| 3881 Register temp = locs()->temp(0).reg(); | 3823 Register temp = locs()->temp(0).reg(); |
| 3882 Register temp2 = locs()->temp(1).reg(); | 3824 Register temp2 = locs()->temp(1).reg(); |
| 3883 // Temp register needs to be manually preserved on allocation slow-path. | 3825 // Temp register needs to be manually preserved on allocation slow-path. |
| 3884 locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32); | 3826 locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32); |
| 3885 | 3827 |
| 3886 ASSERT(temp != result); | 3828 ASSERT(temp != result); |
| 3887 __ MoveRegister(temp, result); | 3829 __ MoveRegister(temp, result); |
| 3888 __ SmiTag(result); | 3830 __ SmiTag(result); |
| 3889 | 3831 |
| 3890 Label done; | 3832 Label done; |
| 3891 __ testl(temp, Immediate(0xC0000000)); | 3833 __ testl(temp, Immediate(0xC0000000)); |
| 3892 __ j(ZERO, &done); | 3834 __ j(ZERO, &done); |
| 3893 BoxAllocationSlowPath::Allocate( | 3835 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
| 3894 compiler, this, compiler->mint_class(), result, temp2); | 3836 result, temp2); |
| 3895 __ movl(FieldAddress(result, Mint::value_offset()), temp); | 3837 __ movl(FieldAddress(result, Mint::value_offset()), temp); |
| 3896 __ movl(FieldAddress(result, Mint::value_offset() + kWordSize), | 3838 __ movl(FieldAddress(result, Mint::value_offset() + kWordSize), |
| 3897 Immediate(0)); | 3839 Immediate(0)); |
| 3898 __ Bind(&done); | 3840 __ Bind(&done); |
| 3899 } | 3841 } |
| 3900 } | 3842 } |
| 3901 } | 3843 } |
| 3902 | 3844 |
| 3903 | 3845 |
| 3904 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3846 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 3905 bool opt) const { | 3847 bool opt) const { |
| 3906 const intptr_t kNumInputs = 2; | 3848 const intptr_t kNumInputs = 2; |
| 3907 const intptr_t kNumTemps = 0; | 3849 const intptr_t kNumTemps = 0; |
| 3908 LocationSummary* summary = new(zone) LocationSummary( | 3850 LocationSummary* summary = new (zone) |
| 3909 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3851 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3910 summary->set_in(0, Location::RequiresFpuRegister()); | 3852 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3911 summary->set_in(1, Location::RequiresFpuRegister()); | 3853 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3912 summary->set_out(0, Location::SameAsFirstInput()); | 3854 summary->set_out(0, Location::SameAsFirstInput()); |
| 3913 return summary; | 3855 return summary; |
| 3914 } | 3856 } |
| 3915 | 3857 |
| 3916 | 3858 |
| 3917 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3859 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3918 XmmRegister left = locs()->in(0).fpu_reg(); | 3860 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3919 XmmRegister right = locs()->in(1).fpu_reg(); | 3861 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3920 | 3862 |
| 3921 ASSERT(locs()->out(0).fpu_reg() == left); | 3863 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3922 | 3864 |
| 3923 switch (op_kind()) { | 3865 switch (op_kind()) { |
| 3924 case Token::kADD: __ addsd(left, right); break; | 3866 case Token::kADD: |
| 3925 case Token::kSUB: __ subsd(left, right); break; | 3867 __ addsd(left, right); |
| 3926 case Token::kMUL: __ mulsd(left, right); break; | 3868 break; |
| 3927 case Token::kDIV: __ divsd(left, right); break; | 3869 case Token::kSUB: |
| 3928 default: UNREACHABLE(); | 3870 __ subsd(left, right); |
| 3871 break; |
| 3872 case Token::kMUL: |
| 3873 __ mulsd(left, right); |
| 3874 break; |
| 3875 case Token::kDIV: |
| 3876 __ divsd(left, right); |
| 3877 break; |
| 3878 default: |
| 3879 UNREACHABLE(); |
| 3929 } | 3880 } |
| 3930 } | 3881 } |
| 3931 | 3882 |
| 3932 | 3883 |
| 3933 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3884 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
| 3934 bool opt) const { | 3885 bool opt) const { |
| 3935 const intptr_t kNumInputs = 1; | 3886 const intptr_t kNumInputs = 1; |
| 3936 const intptr_t kNumTemps = | 3887 const intptr_t kNumTemps = |
| 3937 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; | 3888 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; |
| 3938 LocationSummary* summary = new(zone) LocationSummary( | 3889 LocationSummary* summary = new (zone) |
| 3939 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3890 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3940 summary->set_in(0, Location::RequiresFpuRegister()); | 3891 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3941 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3892 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
| 3942 summary->set_temp(0, Location::RequiresRegister()); | 3893 summary->set_temp(0, Location::RequiresRegister()); |
| 3943 } | 3894 } |
| 3944 summary->set_out(0, Location::RequiresRegister()); | 3895 summary->set_out(0, Location::RequiresRegister()); |
| 3945 return summary; | 3896 return summary; |
| 3946 } | 3897 } |
| 3947 | 3898 |
| 3948 | 3899 |
| 3949 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3900 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3984 BranchInstr* branch) { | 3935 BranchInstr* branch) { |
| 3985 ASSERT(compiler->is_optimizing()); | 3936 ASSERT(compiler->is_optimizing()); |
| 3986 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3937 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3987 Condition true_condition = EmitComparisonCode(compiler, labels); | 3938 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3988 EmitBranchOnCondition(compiler, true_condition, labels); | 3939 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3989 } | 3940 } |
| 3990 | 3941 |
| 3991 | 3942 |
| 3992 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3943 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3993 Label is_true, is_false; | 3944 Label is_true, is_false; |
| 3994 BranchLabels labels = { &is_true, &is_false, &is_false }; | 3945 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 3995 Condition true_condition = EmitComparisonCode(compiler, labels); | 3946 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3996 EmitBranchOnCondition(compiler, true_condition, labels); | 3947 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3997 | 3948 |
| 3998 Register result = locs()->out(0).reg(); | 3949 Register result = locs()->out(0).reg(); |
| 3999 Label done; | 3950 Label done; |
| 4000 __ Bind(&is_false); | 3951 __ Bind(&is_false); |
| 4001 __ LoadObject(result, Bool::False()); | 3952 __ LoadObject(result, Bool::False()); |
| 4002 __ jmp(&done); | 3953 __ jmp(&done); |
| 4003 __ Bind(&is_true); | 3954 __ Bind(&is_true); |
| 4004 __ LoadObject(result, Bool::True()); | 3955 __ LoadObject(result, Bool::True()); |
| 4005 __ Bind(&done); | 3956 __ Bind(&done); |
| 4006 } | 3957 } |
| 4007 | 3958 |
| 4008 | 3959 |
| 4009 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3960 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 4010 bool opt) const { | 3961 bool opt) const { |
| 4011 const intptr_t kNumInputs = 2; | 3962 const intptr_t kNumInputs = 2; |
| 4012 const intptr_t kNumTemps = 0; | 3963 const intptr_t kNumTemps = 0; |
| 4013 LocationSummary* summary = new(zone) LocationSummary( | 3964 LocationSummary* summary = new (zone) |
| 4014 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3965 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4015 summary->set_in(0, Location::RequiresFpuRegister()); | 3966 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4016 summary->set_in(1, Location::RequiresFpuRegister()); | 3967 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4017 summary->set_out(0, Location::SameAsFirstInput()); | 3968 summary->set_out(0, Location::SameAsFirstInput()); |
| 4018 return summary; | 3969 return summary; |
| 4019 } | 3970 } |
| 4020 | 3971 |
| 4021 | 3972 |
| 4022 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3973 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4023 XmmRegister left = locs()->in(0).fpu_reg(); | 3974 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4024 XmmRegister right = locs()->in(1).fpu_reg(); | 3975 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4025 | 3976 |
| 4026 ASSERT(locs()->out(0).fpu_reg() == left); | 3977 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4027 | 3978 |
| 4028 switch (op_kind()) { | 3979 switch (op_kind()) { |
| 4029 case Token::kADD: __ addps(left, right); break; | 3980 case Token::kADD: |
| 4030 case Token::kSUB: __ subps(left, right); break; | 3981 __ addps(left, right); |
| 4031 case Token::kMUL: __ mulps(left, right); break; | 3982 break; |
| 4032 case Token::kDIV: __ divps(left, right); break; | 3983 case Token::kSUB: |
| 4033 default: UNREACHABLE(); | 3984 __ subps(left, right); |
| 3985 break; |
| 3986 case Token::kMUL: |
| 3987 __ mulps(left, right); |
| 3988 break; |
| 3989 case Token::kDIV: |
| 3990 __ divps(left, right); |
| 3991 break; |
| 3992 default: |
| 3993 UNREACHABLE(); |
| 4034 } | 3994 } |
| 4035 } | 3995 } |
| 4036 | 3996 |
| 4037 | 3997 |
| 4038 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 3998 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
| 4039 bool opt) const { | 3999 bool opt) const { |
| 4040 const intptr_t kNumInputs = 2; | 4000 const intptr_t kNumInputs = 2; |
| 4041 const intptr_t kNumTemps = 0; | 4001 const intptr_t kNumTemps = 0; |
| 4042 LocationSummary* summary = new(zone) LocationSummary( | 4002 LocationSummary* summary = new (zone) |
| 4043 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4003 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4044 summary->set_in(0, Location::RequiresFpuRegister()); | 4004 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4045 summary->set_in(1, Location::RequiresFpuRegister()); | 4005 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4046 summary->set_out(0, Location::SameAsFirstInput()); | 4006 summary->set_out(0, Location::SameAsFirstInput()); |
| 4047 return summary; | 4007 return summary; |
| 4048 } | 4008 } |
| 4049 | 4009 |
| 4050 | 4010 |
| 4051 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4011 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4052 XmmRegister left = locs()->in(0).fpu_reg(); | 4012 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4053 XmmRegister right = locs()->in(1).fpu_reg(); | 4013 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4054 | 4014 |
| 4055 ASSERT(locs()->out(0).fpu_reg() == left); | 4015 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4056 | 4016 |
| 4057 switch (op_kind()) { | 4017 switch (op_kind()) { |
| 4058 case Token::kADD: __ addpd(left, right); break; | 4018 case Token::kADD: |
| 4059 case Token::kSUB: __ subpd(left, right); break; | 4019 __ addpd(left, right); |
| 4060 case Token::kMUL: __ mulpd(left, right); break; | 4020 break; |
| 4061 case Token::kDIV: __ divpd(left, right); break; | 4021 case Token::kSUB: |
| 4062 default: UNREACHABLE(); | 4022 __ subpd(left, right); |
| 4023 break; |
| 4024 case Token::kMUL: |
| 4025 __ mulpd(left, right); |
| 4026 break; |
| 4027 case Token::kDIV: |
| 4028 __ divpd(left, right); |
| 4029 break; |
| 4030 default: |
| 4031 UNREACHABLE(); |
| 4063 } | 4032 } |
| 4064 } | 4033 } |
| 4065 | 4034 |
| 4066 | 4035 |
| 4067 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 4036 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 4068 bool opt) const { | 4037 bool opt) const { |
| 4069 const intptr_t kNumInputs = 1; | 4038 const intptr_t kNumInputs = 1; |
| 4070 const intptr_t kNumTemps = 0; | 4039 const intptr_t kNumTemps = 0; |
| 4071 LocationSummary* summary = new(zone) LocationSummary( | 4040 LocationSummary* summary = new (zone) |
| 4072 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4041 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4073 summary->set_in(0, Location::RequiresFpuRegister()); | 4042 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4074 summary->set_out(0, Location::SameAsFirstInput()); | 4043 summary->set_out(0, Location::SameAsFirstInput()); |
| 4075 return summary; | 4044 return summary; |
| 4076 } | 4045 } |
| 4077 | 4046 |
| 4078 | 4047 |
| 4079 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4048 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4080 XmmRegister value = locs()->in(0).fpu_reg(); | 4049 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4081 | 4050 |
| 4082 ASSERT(locs()->out(0).fpu_reg() == value); | 4051 ASSERT(locs()->out(0).fpu_reg() == value); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4095 __ cvtss2sd(value, value); | 4064 __ cvtss2sd(value, value); |
| 4096 break; | 4065 break; |
| 4097 case MethodRecognizer::kFloat32x4ShuffleW: | 4066 case MethodRecognizer::kFloat32x4ShuffleW: |
| 4098 __ shufps(value, value, Immediate(0xFF)); | 4067 __ shufps(value, value, Immediate(0xFF)); |
| 4099 __ cvtss2sd(value, value); | 4068 __ cvtss2sd(value, value); |
| 4100 break; | 4069 break; |
| 4101 case MethodRecognizer::kFloat32x4Shuffle: | 4070 case MethodRecognizer::kFloat32x4Shuffle: |
| 4102 case MethodRecognizer::kInt32x4Shuffle: | 4071 case MethodRecognizer::kInt32x4Shuffle: |
| 4103 __ shufps(value, value, Immediate(mask_)); | 4072 __ shufps(value, value, Immediate(mask_)); |
| 4104 break; | 4073 break; |
| 4105 default: UNREACHABLE(); | 4074 default: |
| 4075 UNREACHABLE(); |
| 4106 } | 4076 } |
| 4107 } | 4077 } |
| 4108 | 4078 |
| 4109 | 4079 |
| 4110 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 4080 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
| 4111 bool opt) const { | 4081 bool opt) const { |
| 4112 const intptr_t kNumInputs = 2; | 4082 const intptr_t kNumInputs = 2; |
| 4113 const intptr_t kNumTemps = 0; | 4083 const intptr_t kNumTemps = 0; |
| 4114 LocationSummary* summary = new(zone) LocationSummary( | 4084 LocationSummary* summary = new (zone) |
| 4115 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4085 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4116 summary->set_in(0, Location::RequiresFpuRegister()); | 4086 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4117 summary->set_in(1, Location::RequiresFpuRegister()); | 4087 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4118 summary->set_out(0, Location::SameAsFirstInput()); | 4088 summary->set_out(0, Location::SameAsFirstInput()); |
| 4119 return summary; | 4089 return summary; |
| 4120 } | 4090 } |
| 4121 | 4091 |
| 4122 | 4092 |
| 4123 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4093 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4124 XmmRegister left = locs()->in(0).fpu_reg(); | 4094 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4125 XmmRegister right = locs()->in(1).fpu_reg(); | 4095 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4126 | 4096 |
| 4127 ASSERT(locs()->out(0).fpu_reg() == left); | 4097 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4128 switch (op_kind()) { | 4098 switch (op_kind()) { |
| 4129 case MethodRecognizer::kFloat32x4ShuffleMix: | 4099 case MethodRecognizer::kFloat32x4ShuffleMix: |
| 4130 case MethodRecognizer::kInt32x4ShuffleMix: | 4100 case MethodRecognizer::kInt32x4ShuffleMix: |
| 4131 __ shufps(left, right, Immediate(mask_)); | 4101 __ shufps(left, right, Immediate(mask_)); |
| 4132 break; | 4102 break; |
| 4133 default: UNREACHABLE(); | 4103 default: |
| 4104 UNREACHABLE(); |
| 4134 } | 4105 } |
| 4135 } | 4106 } |
| 4136 | 4107 |
| 4137 | 4108 |
| 4138 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 4109 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
| 4139 bool opt) const { | 4110 bool opt) const { |
| 4140 const intptr_t kNumInputs = 1; | 4111 const intptr_t kNumInputs = 1; |
| 4141 const intptr_t kNumTemps = 0; | 4112 const intptr_t kNumTemps = 0; |
| 4142 LocationSummary* summary = new(zone) LocationSummary( | 4113 LocationSummary* summary = new (zone) |
| 4143 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4114 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4144 summary->set_in(0, Location::RequiresFpuRegister()); | 4115 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4145 summary->set_out(0, Location::RequiresRegister()); | 4116 summary->set_out(0, Location::RequiresRegister()); |
| 4146 return summary; | 4117 return summary; |
| 4147 } | 4118 } |
| 4148 | 4119 |
| 4149 | 4120 |
| 4150 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4121 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4151 XmmRegister value = locs()->in(0).fpu_reg(); | 4122 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4152 Register out = locs()->out(0).reg(); | 4123 Register out = locs()->out(0).reg(); |
| 4153 | 4124 |
| 4154 __ movmskps(out, value); | 4125 __ movmskps(out, value); |
| 4155 __ SmiTag(out); | 4126 __ SmiTag(out); |
| 4156 } | 4127 } |
| 4157 | 4128 |
| 4158 | 4129 |
| 4159 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 4130 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 4160 Zone* zone, bool opt) const { | 4131 Zone* zone, |
| 4132 bool opt) const { |
| 4161 const intptr_t kNumInputs = 4; | 4133 const intptr_t kNumInputs = 4; |
| 4162 const intptr_t kNumTemps = 0; | 4134 const intptr_t kNumTemps = 0; |
| 4163 LocationSummary* summary = new(zone) LocationSummary( | 4135 LocationSummary* summary = new (zone) |
| 4164 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4136 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4165 summary->set_in(0, Location::RequiresFpuRegister()); | 4137 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4166 summary->set_in(1, Location::RequiresFpuRegister()); | 4138 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4167 summary->set_in(2, Location::RequiresFpuRegister()); | 4139 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4168 summary->set_in(3, Location::RequiresFpuRegister()); | 4140 summary->set_in(3, Location::RequiresFpuRegister()); |
| 4169 summary->set_out(0, Location::SameAsFirstInput()); | 4141 summary->set_out(0, Location::SameAsFirstInput()); |
| 4170 return summary; | 4142 return summary; |
| 4171 } | 4143 } |
| 4172 | 4144 |
| 4173 | 4145 |
| 4174 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4146 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4191 __ movss(Address(ESP, 12), v0); | 4163 __ movss(Address(ESP, 12), v0); |
| 4192 __ movups(v0, Address(ESP, 0)); | 4164 __ movups(v0, Address(ESP, 0)); |
| 4193 __ addl(ESP, Immediate(16)); | 4165 __ addl(ESP, Immediate(16)); |
| 4194 } | 4166 } |
| 4195 | 4167 |
| 4196 | 4168 |
| 4197 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 4169 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4198 bool opt) const { | 4170 bool opt) const { |
| 4199 const intptr_t kNumInputs = 0; | 4171 const intptr_t kNumInputs = 0; |
| 4200 const intptr_t kNumTemps = 0; | 4172 const intptr_t kNumTemps = 0; |
| 4201 LocationSummary* summary = new(zone) LocationSummary( | 4173 LocationSummary* summary = new (zone) |
| 4202 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4174 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4203 summary->set_out(0, Location::RequiresFpuRegister()); | 4175 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4204 return summary; | 4176 return summary; |
| 4205 } | 4177 } |
| 4206 | 4178 |
| 4207 | 4179 |
| 4208 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4180 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4209 XmmRegister value = locs()->out(0).fpu_reg(); | 4181 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4210 __ xorps(value, value); | 4182 __ xorps(value, value); |
| 4211 } | 4183 } |
| 4212 | 4184 |
| 4213 | 4185 |
| 4214 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 4186 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
| 4215 bool opt) const { | 4187 bool opt) const { |
| 4216 const intptr_t kNumInputs = 1; | 4188 const intptr_t kNumInputs = 1; |
| 4217 const intptr_t kNumTemps = 0; | 4189 const intptr_t kNumTemps = 0; |
| 4218 LocationSummary* summary = new(zone) LocationSummary( | 4190 LocationSummary* summary = new (zone) |
| 4219 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4191 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4220 summary->set_in(0, Location::RequiresFpuRegister()); | 4192 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4221 summary->set_out(0, Location::SameAsFirstInput()); | 4193 summary->set_out(0, Location::SameAsFirstInput()); |
| 4222 return summary; | 4194 return summary; |
| 4223 } | 4195 } |
| 4224 | 4196 |
| 4225 | 4197 |
| 4226 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4198 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4227 XmmRegister value = locs()->out(0).fpu_reg(); | 4199 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4228 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); | 4200 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); |
| 4229 // Convert to Float32. | 4201 // Convert to Float32. |
| 4230 __ cvtsd2ss(value, value); | 4202 __ cvtsd2ss(value, value); |
| 4231 // Splat across all lanes. | 4203 // Splat across all lanes. |
| 4232 __ shufps(value, value, Immediate(0x00)); | 4204 __ shufps(value, value, Immediate(0x00)); |
| 4233 } | 4205 } |
| 4234 | 4206 |
| 4235 | 4207 |
| 4236 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 4208 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
| 4237 bool opt) const { | 4209 bool opt) const { |
| 4238 const intptr_t kNumInputs = 2; | 4210 const intptr_t kNumInputs = 2; |
| 4239 const intptr_t kNumTemps = 0; | 4211 const intptr_t kNumTemps = 0; |
| 4240 LocationSummary* summary = new(zone) LocationSummary( | 4212 LocationSummary* summary = new (zone) |
| 4241 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4213 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4242 summary->set_in(0, Location::RequiresFpuRegister()); | 4214 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4243 summary->set_in(1, Location::RequiresFpuRegister()); | 4215 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4244 summary->set_out(0, Location::SameAsFirstInput()); | 4216 summary->set_out(0, Location::SameAsFirstInput()); |
| 4245 return summary; | 4217 return summary; |
| 4246 } | 4218 } |
| 4247 | 4219 |
| 4248 | 4220 |
| 4249 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4221 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4250 XmmRegister left = locs()->in(0).fpu_reg(); | 4222 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4251 XmmRegister right = locs()->in(1).fpu_reg(); | 4223 XmmRegister right = locs()->in(1).fpu_reg(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4265 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 4237 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
| 4266 __ cmppsnlt(left, right); | 4238 __ cmppsnlt(left, right); |
| 4267 break; | 4239 break; |
| 4268 case MethodRecognizer::kFloat32x4LessThan: | 4240 case MethodRecognizer::kFloat32x4LessThan: |
| 4269 __ cmppslt(left, right); | 4241 __ cmppslt(left, right); |
| 4270 break; | 4242 break; |
| 4271 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 4243 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
| 4272 __ cmppsle(left, right); | 4244 __ cmppsle(left, right); |
| 4273 break; | 4245 break; |
| 4274 | 4246 |
| 4275 default: UNREACHABLE(); | 4247 default: |
| 4248 UNREACHABLE(); |
| 4276 } | 4249 } |
| 4277 } | 4250 } |
| 4278 | 4251 |
| 4279 | 4252 |
| 4280 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4253 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
| 4281 bool opt) const { | 4254 bool opt) const { |
| 4282 const intptr_t kNumInputs = 2; | 4255 const intptr_t kNumInputs = 2; |
| 4283 const intptr_t kNumTemps = 0; | 4256 const intptr_t kNumTemps = 0; |
| 4284 LocationSummary* summary = new(zone) LocationSummary( | 4257 LocationSummary* summary = new (zone) |
| 4285 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4258 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4286 summary->set_in(0, Location::RequiresFpuRegister()); | 4259 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4287 summary->set_in(1, Location::RequiresFpuRegister()); | 4260 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4288 summary->set_out(0, Location::SameAsFirstInput()); | 4261 summary->set_out(0, Location::SameAsFirstInput()); |
| 4289 return summary; | 4262 return summary; |
| 4290 } | 4263 } |
| 4291 | 4264 |
| 4292 | 4265 |
| 4293 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4266 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4294 XmmRegister left = locs()->in(0).fpu_reg(); | 4267 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4295 XmmRegister right = locs()->in(1).fpu_reg(); | 4268 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4296 | 4269 |
| 4297 ASSERT(locs()->out(0).fpu_reg() == left); | 4270 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4298 | 4271 |
| 4299 switch (op_kind()) { | 4272 switch (op_kind()) { |
| 4300 case MethodRecognizer::kFloat32x4Min: | 4273 case MethodRecognizer::kFloat32x4Min: |
| 4301 __ minps(left, right); | 4274 __ minps(left, right); |
| 4302 break; | 4275 break; |
| 4303 case MethodRecognizer::kFloat32x4Max: | 4276 case MethodRecognizer::kFloat32x4Max: |
| 4304 __ maxps(left, right); | 4277 __ maxps(left, right); |
| 4305 break; | 4278 break; |
| 4306 default: UNREACHABLE(); | 4279 default: |
| 4280 UNREACHABLE(); |
| 4307 } | 4281 } |
| 4308 } | 4282 } |
| 4309 | 4283 |
| 4310 | 4284 |
| 4311 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4285 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
| 4312 bool opt) const { | 4286 bool opt) const { |
| 4313 const intptr_t kNumInputs = 2; | 4287 const intptr_t kNumInputs = 2; |
| 4314 const intptr_t kNumTemps = 0; | 4288 const intptr_t kNumTemps = 0; |
| 4315 LocationSummary* summary = new(zone) LocationSummary( | 4289 LocationSummary* summary = new (zone) |
| 4316 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4290 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4317 summary->set_in(0, Location::RequiresFpuRegister()); | 4291 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4318 summary->set_in(1, Location::RequiresFpuRegister()); | 4292 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4319 summary->set_out(0, Location::SameAsFirstInput()); | 4293 summary->set_out(0, Location::SameAsFirstInput()); |
| 4320 return summary; | 4294 return summary; |
| 4321 } | 4295 } |
| 4322 | 4296 |
| 4323 | 4297 |
| 4324 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4298 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4325 XmmRegister left = locs()->in(0).fpu_reg(); | 4299 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4326 XmmRegister right = locs()->in(1).fpu_reg(); | 4300 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4327 | 4301 |
| 4328 ASSERT(locs()->out(0).fpu_reg() == left); | 4302 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4329 | 4303 |
| 4330 switch (op_kind()) { | 4304 switch (op_kind()) { |
| 4331 case MethodRecognizer::kFloat32x4Scale: | 4305 case MethodRecognizer::kFloat32x4Scale: |
| 4332 __ cvtsd2ss(left, left); | 4306 __ cvtsd2ss(left, left); |
| 4333 __ shufps(left, left, Immediate(0x00)); | 4307 __ shufps(left, left, Immediate(0x00)); |
| 4334 __ mulps(left, right); | 4308 __ mulps(left, right); |
| 4335 break; | 4309 break; |
| 4336 default: UNREACHABLE(); | 4310 default: |
| 4311 UNREACHABLE(); |
| 4337 } | 4312 } |
| 4338 } | 4313 } |
| 4339 | 4314 |
| 4340 | 4315 |
| 4341 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4316 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
| 4342 bool opt) const { | 4317 bool opt) const { |
| 4343 const intptr_t kNumInputs = 1; | 4318 const intptr_t kNumInputs = 1; |
| 4344 const intptr_t kNumTemps = 0; | 4319 const intptr_t kNumTemps = 0; |
| 4345 LocationSummary* summary = new(zone) LocationSummary( | 4320 LocationSummary* summary = new (zone) |
| 4346 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4321 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4347 summary->set_in(0, Location::RequiresFpuRegister()); | 4322 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4348 summary->set_out(0, Location::SameAsFirstInput()); | 4323 summary->set_out(0, Location::SameAsFirstInput()); |
| 4349 return summary; | 4324 return summary; |
| 4350 } | 4325 } |
| 4351 | 4326 |
| 4352 | 4327 |
| 4353 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4328 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4354 XmmRegister left = locs()->in(0).fpu_reg(); | 4329 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4355 | 4330 |
| 4356 ASSERT(locs()->out(0).fpu_reg() == left); | 4331 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4357 | 4332 |
| 4358 switch (op_kind()) { | 4333 switch (op_kind()) { |
| 4359 case MethodRecognizer::kFloat32x4Sqrt: | 4334 case MethodRecognizer::kFloat32x4Sqrt: |
| 4360 __ sqrtps(left); | 4335 __ sqrtps(left); |
| 4361 break; | 4336 break; |
| 4362 case MethodRecognizer::kFloat32x4Reciprocal: | 4337 case MethodRecognizer::kFloat32x4Reciprocal: |
| 4363 __ reciprocalps(left); | 4338 __ reciprocalps(left); |
| 4364 break; | 4339 break; |
| 4365 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4340 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 4366 __ rsqrtps(left); | 4341 __ rsqrtps(left); |
| 4367 break; | 4342 break; |
| 4368 default: UNREACHABLE(); | 4343 default: |
| 4344 UNREACHABLE(); |
| 4369 } | 4345 } |
| 4370 } | 4346 } |
| 4371 | 4347 |
| 4372 | 4348 |
| 4373 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4349 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4374 bool opt) const { | 4350 bool opt) const { |
| 4375 const intptr_t kNumInputs = 1; | 4351 const intptr_t kNumInputs = 1; |
| 4376 const intptr_t kNumTemps = 0; | 4352 const intptr_t kNumTemps = 0; |
| 4377 LocationSummary* summary = new(zone) LocationSummary( | 4353 LocationSummary* summary = new (zone) |
| 4378 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4354 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4379 summary->set_in(0, Location::RequiresFpuRegister()); | 4355 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4380 summary->set_out(0, Location::SameAsFirstInput()); | 4356 summary->set_out(0, Location::SameAsFirstInput()); |
| 4381 return summary; | 4357 return summary; |
| 4382 } | 4358 } |
| 4383 | 4359 |
| 4384 | 4360 |
| 4385 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4361 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4386 XmmRegister left = locs()->in(0).fpu_reg(); | 4362 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4387 | 4363 |
| 4388 ASSERT(locs()->out(0).fpu_reg() == left); | 4364 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4389 switch (op_kind()) { | 4365 switch (op_kind()) { |
| 4390 case MethodRecognizer::kFloat32x4Negate: | 4366 case MethodRecognizer::kFloat32x4Negate: |
| 4391 __ negateps(left); | 4367 __ negateps(left); |
| 4392 break; | 4368 break; |
| 4393 case MethodRecognizer::kFloat32x4Absolute: | 4369 case MethodRecognizer::kFloat32x4Absolute: |
| 4394 __ absps(left); | 4370 __ absps(left); |
| 4395 break; | 4371 break; |
| 4396 default: UNREACHABLE(); | 4372 default: |
| 4373 UNREACHABLE(); |
| 4397 } | 4374 } |
| 4398 } | 4375 } |
| 4399 | 4376 |
| 4400 | 4377 |
| 4401 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4378 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
| 4402 bool opt) const { | 4379 bool opt) const { |
| 4403 const intptr_t kNumInputs = 3; | 4380 const intptr_t kNumInputs = 3; |
| 4404 const intptr_t kNumTemps = 0; | 4381 const intptr_t kNumTemps = 0; |
| 4405 LocationSummary* summary = new(zone) LocationSummary( | 4382 LocationSummary* summary = new (zone) |
| 4406 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4383 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4407 summary->set_in(0, Location::RequiresFpuRegister()); | 4384 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4408 summary->set_in(1, Location::RequiresFpuRegister()); | 4385 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4409 summary->set_in(2, Location::RequiresFpuRegister()); | 4386 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4410 summary->set_out(0, Location::SameAsFirstInput()); | 4387 summary->set_out(0, Location::SameAsFirstInput()); |
| 4411 return summary; | 4388 return summary; |
| 4412 } | 4389 } |
| 4413 | 4390 |
| 4414 | 4391 |
| 4415 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4392 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4416 XmmRegister left = locs()->in(0).fpu_reg(); | 4393 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4417 XmmRegister lower = locs()->in(1).fpu_reg(); | 4394 XmmRegister lower = locs()->in(1).fpu_reg(); |
| 4418 XmmRegister upper = locs()->in(2).fpu_reg(); | 4395 XmmRegister upper = locs()->in(2).fpu_reg(); |
| 4419 ASSERT(locs()->out(0).fpu_reg() == left); | 4396 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4420 __ minps(left, upper); | 4397 __ minps(left, upper); |
| 4421 __ maxps(left, lower); | 4398 __ maxps(left, lower); |
| 4422 } | 4399 } |
| 4423 | 4400 |
| 4424 | 4401 |
| 4425 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4402 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
| 4426 bool opt) const { | 4403 bool opt) const { |
| 4427 const intptr_t kNumInputs = 2; | 4404 const intptr_t kNumInputs = 2; |
| 4428 const intptr_t kNumTemps = 0; | 4405 const intptr_t kNumTemps = 0; |
| 4429 LocationSummary* summary = new(zone) LocationSummary( | 4406 LocationSummary* summary = new (zone) |
| 4430 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4407 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4431 summary->set_in(0, Location::RequiresFpuRegister()); | 4408 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4432 summary->set_in(1, Location::RequiresFpuRegister()); | 4409 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4433 summary->set_out(0, Location::SameAsFirstInput()); | 4410 summary->set_out(0, Location::SameAsFirstInput()); |
| 4434 return summary; | 4411 return summary; |
| 4435 } | 4412 } |
| 4436 | 4413 |
| 4437 | 4414 |
| 4438 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4415 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4439 XmmRegister replacement = locs()->in(0).fpu_reg(); | 4416 XmmRegister replacement = locs()->in(0).fpu_reg(); |
| 4440 XmmRegister value = locs()->in(1).fpu_reg(); | 4417 XmmRegister value = locs()->in(1).fpu_reg(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4479 __ cvtsd2ss(replacement, replacement); | 4456 __ cvtsd2ss(replacement, replacement); |
| 4480 __ subl(ESP, Immediate(16)); | 4457 __ subl(ESP, Immediate(16)); |
| 4481 // Move value to stack. | 4458 // Move value to stack. |
| 4482 __ movups(Address(ESP, 0), value); | 4459 __ movups(Address(ESP, 0), value); |
| 4483 // Write over W value. | 4460 // Write over W value. |
| 4484 __ movss(Address(ESP, 12), replacement); | 4461 __ movss(Address(ESP, 12), replacement); |
| 4485 // Move updated value into output register. | 4462 // Move updated value into output register. |
| 4486 __ movups(replacement, Address(ESP, 0)); | 4463 __ movups(replacement, Address(ESP, 0)); |
| 4487 __ addl(ESP, Immediate(16)); | 4464 __ addl(ESP, Immediate(16)); |
| 4488 break; | 4465 break; |
| 4489 default: UNREACHABLE(); | 4466 default: |
| 4467 UNREACHABLE(); |
| 4490 } | 4468 } |
| 4491 } | 4469 } |
| 4492 | 4470 |
| 4493 | 4471 |
| 4494 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4472 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
| 4495 bool opt) const { | 4473 bool opt) const { |
| 4496 const intptr_t kNumInputs = 1; | 4474 const intptr_t kNumInputs = 1; |
| 4497 const intptr_t kNumTemps = 0; | 4475 const intptr_t kNumTemps = 0; |
| 4498 LocationSummary* summary = new(zone) LocationSummary( | 4476 LocationSummary* summary = new (zone) |
| 4499 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4477 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4500 summary->set_in(0, Location::RequiresFpuRegister()); | 4478 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4501 summary->set_out(0, Location::SameAsFirstInput()); | 4479 summary->set_out(0, Location::SameAsFirstInput()); |
| 4502 return summary; | 4480 return summary; |
| 4503 } | 4481 } |
| 4504 | 4482 |
| 4505 | 4483 |
| 4506 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4484 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4507 // NOP. | 4485 // NOP. |
| 4508 } | 4486 } |
| 4509 | 4487 |
| 4510 | 4488 |
| 4511 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4489 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 4512 bool opt) const { | 4490 bool opt) const { |
| 4513 const intptr_t kNumInputs = 1; | 4491 const intptr_t kNumInputs = 1; |
| 4514 const intptr_t kNumTemps = 0; | 4492 const intptr_t kNumTemps = 0; |
| 4515 LocationSummary* summary = new(zone) LocationSummary( | 4493 LocationSummary* summary = new (zone) |
| 4516 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4494 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4517 summary->set_in(0, Location::RequiresFpuRegister()); | 4495 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4518 summary->set_out(0, Location::SameAsFirstInput()); | 4496 summary->set_out(0, Location::SameAsFirstInput()); |
| 4519 return summary; | 4497 return summary; |
| 4520 } | 4498 } |
| 4521 | 4499 |
| 4522 | 4500 |
| 4523 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4501 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4524 XmmRegister value = locs()->in(0).fpu_reg(); | 4502 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4525 | 4503 |
| 4526 ASSERT(locs()->out(0).fpu_reg() == value); | 4504 ASSERT(locs()->out(0).fpu_reg() == value); |
| 4527 | 4505 |
| 4528 switch (op_kind()) { | 4506 switch (op_kind()) { |
| 4529 case MethodRecognizer::kFloat64x2GetX: | 4507 case MethodRecognizer::kFloat64x2GetX: |
| 4530 // nop. | 4508 // nop. |
| 4531 break; | 4509 break; |
| 4532 case MethodRecognizer::kFloat64x2GetY: | 4510 case MethodRecognizer::kFloat64x2GetY: |
| 4533 __ shufpd(value, value, Immediate(0x33)); | 4511 __ shufpd(value, value, Immediate(0x33)); |
| 4534 break; | 4512 break; |
| 4535 default: UNREACHABLE(); | 4513 default: |
| 4514 UNREACHABLE(); |
| 4536 } | 4515 } |
| 4537 } | 4516 } |
| 4538 | 4517 |
| 4539 | 4518 |
| 4540 | |
| 4541 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4519 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4542 bool opt) const { | 4520 bool opt) const { |
| 4543 const intptr_t kNumInputs = 0; | 4521 const intptr_t kNumInputs = 0; |
| 4544 const intptr_t kNumTemps = 0; | 4522 const intptr_t kNumTemps = 0; |
| 4545 LocationSummary* summary = new(zone) LocationSummary( | 4523 LocationSummary* summary = new (zone) |
| 4546 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4524 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4547 summary->set_out(0, Location::RequiresFpuRegister()); | 4525 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4548 return summary; | 4526 return summary; |
| 4549 } | 4527 } |
| 4550 | 4528 |
| 4551 | 4529 |
| 4552 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4530 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4553 XmmRegister value = locs()->out(0).fpu_reg(); | 4531 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4554 __ xorpd(value, value); | 4532 __ xorpd(value, value); |
| 4555 } | 4533 } |
| 4556 | 4534 |
| 4557 | 4535 |
| 4558 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4536 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
| 4559 bool opt) const { | 4537 bool opt) const { |
| 4560 const intptr_t kNumInputs = 1; | 4538 const intptr_t kNumInputs = 1; |
| 4561 const intptr_t kNumTemps = 0; | 4539 const intptr_t kNumTemps = 0; |
| 4562 LocationSummary* summary = new(zone) LocationSummary( | 4540 LocationSummary* summary = new (zone) |
| 4563 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4541 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4564 summary->set_in(0, Location::RequiresFpuRegister()); | 4542 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4565 summary->set_out(0, Location::SameAsFirstInput()); | 4543 summary->set_out(0, Location::SameAsFirstInput()); |
| 4566 return summary; | 4544 return summary; |
| 4567 } | 4545 } |
| 4568 | 4546 |
| 4569 | 4547 |
| 4570 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4548 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4571 XmmRegister value = locs()->out(0).fpu_reg(); | 4549 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4572 __ shufpd(value, value, Immediate(0x0)); | 4550 __ shufpd(value, value, Immediate(0x0)); |
| 4573 } | 4551 } |
| 4574 | 4552 |
| 4575 | 4553 |
| 4576 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4554 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
| 4577 Zone* zone, bool opt) const { | 4555 Zone* zone, |
| 4556 bool opt) const { |
| 4578 const intptr_t kNumInputs = 2; | 4557 const intptr_t kNumInputs = 2; |
| 4579 const intptr_t kNumTemps = 0; | 4558 const intptr_t kNumTemps = 0; |
| 4580 LocationSummary* summary = new(zone) LocationSummary( | 4559 LocationSummary* summary = new (zone) |
| 4581 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4560 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4582 summary->set_in(0, Location::RequiresFpuRegister()); | 4561 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4583 summary->set_in(1, Location::RequiresFpuRegister()); | 4562 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4584 summary->set_out(0, Location::SameAsFirstInput()); | 4563 summary->set_out(0, Location::SameAsFirstInput()); |
| 4585 return summary; | 4564 return summary; |
| 4586 } | 4565 } |
| 4587 | 4566 |
| 4588 | 4567 |
| 4589 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4568 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4590 XmmRegister v0 = locs()->in(0).fpu_reg(); | 4569 XmmRegister v0 = locs()->in(0).fpu_reg(); |
| 4591 XmmRegister v1 = locs()->in(1).fpu_reg(); | 4570 XmmRegister v1 = locs()->in(1).fpu_reg(); |
| 4592 ASSERT(v0 == locs()->out(0).fpu_reg()); | 4571 ASSERT(v0 == locs()->out(0).fpu_reg()); |
| 4593 // shufpd mask 0x0 results in: | 4572 // shufpd mask 0x0 results in: |
| 4594 // Lower 64-bits of v0 = Lower 64-bits of v0. | 4573 // Lower 64-bits of v0 = Lower 64-bits of v0. |
| 4595 // Upper 64-bits of v0 = Lower 64-bits of v1. | 4574 // Upper 64-bits of v0 = Lower 64-bits of v1. |
| 4596 __ shufpd(v0, v1, Immediate(0x0)); | 4575 __ shufpd(v0, v1, Immediate(0x0)); |
| 4597 } | 4576 } |
| 4598 | 4577 |
| 4599 | 4578 |
| 4600 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4579 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
| 4601 Zone* zone, bool opt) const { | 4580 Zone* zone, |
| 4581 bool opt) const { |
| 4602 const intptr_t kNumInputs = 1; | 4582 const intptr_t kNumInputs = 1; |
| 4603 const intptr_t kNumTemps = 0; | 4583 const intptr_t kNumTemps = 0; |
| 4604 LocationSummary* summary = new(zone) LocationSummary( | 4584 LocationSummary* summary = new (zone) |
| 4605 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4585 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4606 summary->set_in(0, Location::RequiresFpuRegister()); | 4586 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4607 summary->set_out(0, Location::SameAsFirstInput()); | 4587 summary->set_out(0, Location::SameAsFirstInput()); |
| 4608 return summary; | 4588 return summary; |
| 4609 } | 4589 } |
| 4610 | 4590 |
| 4611 | 4591 |
| 4612 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4592 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4613 XmmRegister value = locs()->out(0).fpu_reg(); | 4593 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4614 __ cvtpd2ps(value, value); | 4594 __ cvtpd2ps(value, value); |
| 4615 } | 4595 } |
| 4616 | 4596 |
| 4617 | 4597 |
| 4618 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4598 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
| 4619 Zone* zone, bool opt) const { | 4599 Zone* zone, |
| 4600 bool opt) const { |
| 4620 const intptr_t kNumInputs = 1; | 4601 const intptr_t kNumInputs = 1; |
| 4621 const intptr_t kNumTemps = 0; | 4602 const intptr_t kNumTemps = 0; |
| 4622 LocationSummary* summary = new(zone) LocationSummary( | 4603 LocationSummary* summary = new (zone) |
| 4623 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4604 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4624 summary->set_in(0, Location::RequiresFpuRegister()); | 4605 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4625 summary->set_out(0, Location::SameAsFirstInput()); | 4606 summary->set_out(0, Location::SameAsFirstInput()); |
| 4626 return summary; | 4607 return summary; |
| 4627 } | 4608 } |
| 4628 | 4609 |
| 4629 | 4610 |
| 4630 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4611 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4631 XmmRegister value = locs()->out(0).fpu_reg(); | 4612 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4632 __ cvtps2pd(value, value); | 4613 __ cvtps2pd(value, value); |
| 4633 } | 4614 } |
| 4634 | 4615 |
| 4635 | 4616 |
| 4636 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4617 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4637 bool opt) const { | 4618 bool opt) const { |
| 4638 const intptr_t kNumInputs = 1; | 4619 const intptr_t kNumInputs = 1; |
| 4639 const intptr_t kNumTemps = 0; | 4620 const intptr_t kNumTemps = 0; |
| 4640 LocationSummary* summary = new(zone) LocationSummary( | 4621 LocationSummary* summary = new (zone) |
| 4641 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4622 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4642 summary->set_in(0, Location::RequiresFpuRegister()); | 4623 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4643 if (representation() == kTagged) { | 4624 if (representation() == kTagged) { |
| 4644 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4625 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
| 4645 summary->set_out(0, Location::RequiresRegister()); | 4626 summary->set_out(0, Location::RequiresRegister()); |
| 4646 } else { | 4627 } else { |
| 4647 ASSERT(representation() == kUnboxedFloat64x2); | 4628 ASSERT(representation() == kUnboxedFloat64x2); |
| 4648 summary->set_out(0, Location::SameAsFirstInput()); | 4629 summary->set_out(0, Location::SameAsFirstInput()); |
| 4649 } | 4630 } |
| 4650 return summary; | 4631 return summary; |
| 4651 } | 4632 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4664 case MethodRecognizer::kFloat64x2Abs: | 4645 case MethodRecognizer::kFloat64x2Abs: |
| 4665 __ abspd(left); | 4646 __ abspd(left); |
| 4666 break; | 4647 break; |
| 4667 case MethodRecognizer::kFloat64x2Sqrt: | 4648 case MethodRecognizer::kFloat64x2Sqrt: |
| 4668 __ sqrtpd(left); | 4649 __ sqrtpd(left); |
| 4669 break; | 4650 break; |
| 4670 case MethodRecognizer::kFloat64x2GetSignMask: | 4651 case MethodRecognizer::kFloat64x2GetSignMask: |
| 4671 __ movmskpd(locs()->out(0).reg(), left); | 4652 __ movmskpd(locs()->out(0).reg(), left); |
| 4672 __ SmiTag(locs()->out(0).reg()); | 4653 __ SmiTag(locs()->out(0).reg()); |
| 4673 break; | 4654 break; |
| 4674 default: UNREACHABLE(); | 4655 default: |
| 4656 UNREACHABLE(); |
| 4675 } | 4657 } |
| 4676 } | 4658 } |
| 4677 | 4659 |
| 4678 | 4660 |
| 4679 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 4661 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
| 4680 bool opt) const { | 4662 bool opt) const { |
| 4681 const intptr_t kNumInputs = 2; | 4663 const intptr_t kNumInputs = 2; |
| 4682 const intptr_t kNumTemps = 0; | 4664 const intptr_t kNumTemps = 0; |
| 4683 LocationSummary* summary = new(zone) LocationSummary( | 4665 LocationSummary* summary = new (zone) |
| 4684 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4685 summary->set_in(0, Location::RequiresFpuRegister()); | 4667 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4686 summary->set_in(1, Location::RequiresFpuRegister()); | 4668 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4687 summary->set_out(0, Location::SameAsFirstInput()); | 4669 summary->set_out(0, Location::SameAsFirstInput()); |
| 4688 return summary; | 4670 return summary; |
| 4689 } | 4671 } |
| 4690 | 4672 |
| 4691 | 4673 |
| 4692 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4674 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4693 XmmRegister left = locs()->in(0).fpu_reg(); | 4675 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4694 XmmRegister right = locs()->in(1).fpu_reg(); | 4676 XmmRegister right = locs()->in(1).fpu_reg(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 4718 // Move updated value into output register. | 4700 // Move updated value into output register. |
| 4719 __ movups(left, Address(ESP, 0)); | 4701 __ movups(left, Address(ESP, 0)); |
| 4720 __ addl(ESP, Immediate(16)); | 4702 __ addl(ESP, Immediate(16)); |
| 4721 break; | 4703 break; |
| 4722 case MethodRecognizer::kFloat64x2Min: | 4704 case MethodRecognizer::kFloat64x2Min: |
| 4723 __ minpd(left, right); | 4705 __ minpd(left, right); |
| 4724 break; | 4706 break; |
| 4725 case MethodRecognizer::kFloat64x2Max: | 4707 case MethodRecognizer::kFloat64x2Max: |
| 4726 __ maxpd(left, right); | 4708 __ maxpd(left, right); |
| 4727 break; | 4709 break; |
| 4728 default: UNREACHABLE(); | 4710 default: |
| 4711 UNREACHABLE(); |
| 4729 } | 4712 } |
| 4730 } | 4713 } |
| 4731 | 4714 |
| 4732 | 4715 |
| 4733 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( | 4716 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
| 4734 Zone* zone, bool opt) const { | 4717 bool opt) const { |
| 4735 const intptr_t kNumInputs = 4; | 4718 const intptr_t kNumInputs = 4; |
| 4736 const intptr_t kNumTemps = 0; | 4719 const intptr_t kNumTemps = 0; |
| 4737 LocationSummary* summary = new(zone) LocationSummary( | 4720 LocationSummary* summary = new (zone) |
| 4738 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4721 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4739 summary->set_in(0, Location::RequiresRegister()); | 4722 summary->set_in(0, Location::RequiresRegister()); |
| 4740 summary->set_in(1, Location::RequiresRegister()); | 4723 summary->set_in(1, Location::RequiresRegister()); |
| 4741 summary->set_in(2, Location::RequiresRegister()); | 4724 summary->set_in(2, Location::RequiresRegister()); |
| 4742 summary->set_in(3, Location::RequiresRegister()); | 4725 summary->set_in(3, Location::RequiresRegister()); |
| 4743 summary->set_out(0, Location::RequiresFpuRegister()); | 4726 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4744 return summary; | 4727 return summary; |
| 4745 } | 4728 } |
| 4746 | 4729 |
| 4747 | 4730 |
| 4748 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4731 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4749 Register v0 = locs()->in(0).reg(); | 4732 Register v0 = locs()->in(0).reg(); |
| 4750 Register v1 = locs()->in(1).reg(); | 4733 Register v1 = locs()->in(1).reg(); |
| 4751 Register v2 = locs()->in(2).reg(); | 4734 Register v2 = locs()->in(2).reg(); |
| 4752 Register v3 = locs()->in(3).reg(); | 4735 Register v3 = locs()->in(3).reg(); |
| 4753 XmmRegister result = locs()->out(0).fpu_reg(); | 4736 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4754 __ subl(ESP, Immediate(4 * kInt32Size)); | 4737 __ subl(ESP, Immediate(4 * kInt32Size)); |
| 4755 __ movl(Address(ESP, 0 * kInt32Size), v0); | 4738 __ movl(Address(ESP, 0 * kInt32Size), v0); |
| 4756 __ movl(Address(ESP, 1 * kInt32Size), v1); | 4739 __ movl(Address(ESP, 1 * kInt32Size), v1); |
| 4757 __ movl(Address(ESP, 2 * kInt32Size), v2); | 4740 __ movl(Address(ESP, 2 * kInt32Size), v2); |
| 4758 __ movl(Address(ESP, 3 * kInt32Size), v3); | 4741 __ movl(Address(ESP, 3 * kInt32Size), v3); |
| 4759 __ movups(result, Address(ESP, 0)); | 4742 __ movups(result, Address(ESP, 0)); |
| 4760 __ addl(ESP, Immediate(4 * kInt32Size)); | 4743 __ addl(ESP, Immediate(4 * kInt32Size)); |
| 4761 } | 4744 } |
| 4762 | 4745 |
| 4763 | 4746 |
| 4764 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4747 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
| 4765 Zone* zone, bool opt) const { | 4748 Zone* zone, |
| 4749 bool opt) const { |
| 4766 const intptr_t kNumInputs = 4; | 4750 const intptr_t kNumInputs = 4; |
| 4767 const intptr_t kNumTemps = 0; | 4751 const intptr_t kNumTemps = 0; |
| 4768 LocationSummary* summary = new(zone) LocationSummary( | 4752 LocationSummary* summary = new (zone) |
| 4769 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4753 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4770 summary->set_in(0, Location::RequiresRegister()); | 4754 summary->set_in(0, Location::RequiresRegister()); |
| 4771 summary->set_in(1, Location::RequiresRegister()); | 4755 summary->set_in(1, Location::RequiresRegister()); |
| 4772 summary->set_in(2, Location::RequiresRegister()); | 4756 summary->set_in(2, Location::RequiresRegister()); |
| 4773 summary->set_in(3, Location::RequiresRegister()); | 4757 summary->set_in(3, Location::RequiresRegister()); |
| 4774 summary->set_out(0, Location::RequiresFpuRegister()); | 4758 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4775 return summary; | 4759 return summary; |
| 4776 } | 4760 } |
| 4777 | 4761 |
| 4778 | 4762 |
| 4779 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4763 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4821 | 4805 |
| 4822 __ movups(result, Address(ESP, 0)); | 4806 __ movups(result, Address(ESP, 0)); |
| 4823 __ addl(ESP, Immediate(16)); | 4807 __ addl(ESP, Immediate(16)); |
| 4824 } | 4808 } |
| 4825 | 4809 |
| 4826 | 4810 |
| 4827 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4811 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4828 bool opt) const { | 4812 bool opt) const { |
| 4829 const intptr_t kNumInputs = 1; | 4813 const intptr_t kNumInputs = 1; |
| 4830 const intptr_t kNumTemps = 0; | 4814 const intptr_t kNumTemps = 0; |
| 4831 LocationSummary* summary = new(zone) LocationSummary( | 4815 LocationSummary* summary = new (zone) |
| 4832 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4816 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4833 summary->set_in(0, Location::RequiresFpuRegister()); | 4817 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4834 summary->set_out(0, Location::RequiresRegister()); | 4818 summary->set_out(0, Location::RequiresRegister()); |
| 4835 return summary; | 4819 return summary; |
| 4836 } | 4820 } |
| 4837 | 4821 |
| 4838 | 4822 |
| 4839 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4823 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4840 XmmRegister value = locs()->in(0).fpu_reg(); | 4824 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4841 Register result = locs()->out(0).reg(); | 4825 Register result = locs()->out(0).reg(); |
| 4842 Label done; | 4826 Label done; |
| 4843 Label non_zero; | 4827 Label non_zero; |
| 4844 __ subl(ESP, Immediate(16)); | 4828 __ subl(ESP, Immediate(16)); |
| 4845 // Move value to stack. | 4829 // Move value to stack. |
| 4846 __ movups(Address(ESP, 0), value); | 4830 __ movups(Address(ESP, 0), value); |
| 4847 switch (op_kind()) { | 4831 switch (op_kind()) { |
| 4848 case MethodRecognizer::kInt32x4GetFlagX: | 4832 case MethodRecognizer::kInt32x4GetFlagX: |
| 4849 __ movl(result, Address(ESP, 0)); | 4833 __ movl(result, Address(ESP, 0)); |
| 4850 break; | 4834 break; |
| 4851 case MethodRecognizer::kInt32x4GetFlagY: | 4835 case MethodRecognizer::kInt32x4GetFlagY: |
| 4852 __ movl(result, Address(ESP, 4)); | 4836 __ movl(result, Address(ESP, 4)); |
| 4853 break; | 4837 break; |
| 4854 case MethodRecognizer::kInt32x4GetFlagZ: | 4838 case MethodRecognizer::kInt32x4GetFlagZ: |
| 4855 __ movl(result, Address(ESP, 8)); | 4839 __ movl(result, Address(ESP, 8)); |
| 4856 break; | 4840 break; |
| 4857 case MethodRecognizer::kInt32x4GetFlagW: | 4841 case MethodRecognizer::kInt32x4GetFlagW: |
| 4858 __ movl(result, Address(ESP, 12)); | 4842 __ movl(result, Address(ESP, 12)); |
| 4859 break; | 4843 break; |
| 4860 default: UNREACHABLE(); | 4844 default: |
| 4845 UNREACHABLE(); |
| 4861 } | 4846 } |
| 4862 __ addl(ESP, Immediate(16)); | 4847 __ addl(ESP, Immediate(16)); |
| 4863 __ testl(result, result); | 4848 __ testl(result, result); |
| 4864 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); | 4849 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); |
| 4865 __ LoadObject(result, Bool::False()); | 4850 __ LoadObject(result, Bool::False()); |
| 4866 __ jmp(&done); | 4851 __ jmp(&done); |
| 4867 __ Bind(&non_zero); | 4852 __ Bind(&non_zero); |
| 4868 __ LoadObject(result, Bool::True()); | 4853 __ LoadObject(result, Bool::True()); |
| 4869 __ Bind(&done); | 4854 __ Bind(&done); |
| 4870 } | 4855 } |
| 4871 | 4856 |
| 4872 | 4857 |
| 4873 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4858 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
| 4874 bool opt) const { | 4859 bool opt) const { |
| 4875 const intptr_t kNumInputs = 3; | 4860 const intptr_t kNumInputs = 3; |
| 4876 const intptr_t kNumTemps = 1; | 4861 const intptr_t kNumTemps = 1; |
| 4877 LocationSummary* summary = new(zone) LocationSummary( | 4862 LocationSummary* summary = new (zone) |
| 4878 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4863 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4879 summary->set_in(0, Location::RequiresFpuRegister()); | 4864 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4880 summary->set_in(1, Location::RequiresFpuRegister()); | 4865 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4881 summary->set_in(2, Location::RequiresFpuRegister()); | 4866 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4882 summary->set_temp(0, Location::RequiresFpuRegister()); | 4867 summary->set_temp(0, Location::RequiresFpuRegister()); |
| 4883 summary->set_out(0, Location::SameAsFirstInput()); | 4868 summary->set_out(0, Location::SameAsFirstInput()); |
| 4884 return summary; | 4869 return summary; |
| 4885 } | 4870 } |
| 4886 | 4871 |
| 4887 | 4872 |
| 4888 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4873 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4902 __ andps(temp, falseValue); | 4887 __ andps(temp, falseValue); |
| 4903 // out = mask | temp. | 4888 // out = mask | temp. |
| 4904 __ orps(mask, temp); | 4889 __ orps(mask, temp); |
| 4905 } | 4890 } |
| 4906 | 4891 |
| 4907 | 4892 |
| 4908 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 4893 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4909 bool opt) const { | 4894 bool opt) const { |
| 4910 const intptr_t kNumInputs = 2; | 4895 const intptr_t kNumInputs = 2; |
| 4911 const intptr_t kNumTemps = 0; | 4896 const intptr_t kNumTemps = 0; |
| 4912 LocationSummary* summary = new(zone) LocationSummary( | 4897 LocationSummary* summary = new (zone) |
| 4913 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4898 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4914 summary->set_in(0, Location::RequiresFpuRegister()); | 4899 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4915 summary->set_in(1, Location::RequiresRegister()); | 4900 summary->set_in(1, Location::RequiresRegister()); |
| 4916 summary->set_out(0, Location::SameAsFirstInput()); | 4901 summary->set_out(0, Location::SameAsFirstInput()); |
| 4917 return summary; | 4902 return summary; |
| 4918 } | 4903 } |
| 4919 | 4904 |
| 4920 | 4905 |
| 4921 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4906 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4922 XmmRegister mask = locs()->in(0).fpu_reg(); | 4907 XmmRegister mask = locs()->in(0).fpu_reg(); |
| 4923 Register flag = locs()->in(1).reg(); | 4908 Register flag = locs()->in(1).reg(); |
| 4924 ASSERT(mask == locs()->out(0).fpu_reg()); | 4909 ASSERT(mask == locs()->out(0).fpu_reg()); |
| 4925 __ subl(ESP, Immediate(16)); | 4910 __ subl(ESP, Immediate(16)); |
| 4926 // Copy mask to stack. | 4911 // Copy mask to stack. |
| 4927 __ movups(Address(ESP, 0), mask); | 4912 __ movups(Address(ESP, 0), mask); |
| 4928 Label falsePath, exitPath; | 4913 Label falsePath, exitPath; |
| 4929 __ CompareObject(flag, Bool::True()); | 4914 __ CompareObject(flag, Bool::True()); |
| 4930 __ j(NOT_EQUAL, &falsePath); | 4915 __ j(NOT_EQUAL, &falsePath); |
| 4931 switch (op_kind()) { | 4916 switch (op_kind()) { |
| 4932 case MethodRecognizer::kInt32x4WithFlagX: | 4917 case MethodRecognizer::kInt32x4WithFlagX: |
| 4933 __ movl(Address(ESP, 0), Immediate(0xFFFFFFFF)); | 4918 __ movl(Address(ESP, 0), Immediate(0xFFFFFFFF)); |
| 4934 __ jmp(&exitPath); | 4919 __ jmp(&exitPath); |
| 4935 __ Bind(&falsePath); | 4920 __ Bind(&falsePath); |
| 4936 __ movl(Address(ESP, 0), Immediate(0x0)); | 4921 __ movl(Address(ESP, 0), Immediate(0x0)); |
| 4937 break; | 4922 break; |
| 4938 case MethodRecognizer::kInt32x4WithFlagY: | 4923 case MethodRecognizer::kInt32x4WithFlagY: |
| 4939 __ movl(Address(ESP, 4), Immediate(0xFFFFFFFF)); | 4924 __ movl(Address(ESP, 4), Immediate(0xFFFFFFFF)); |
| 4940 __ jmp(&exitPath); | 4925 __ jmp(&exitPath); |
| 4941 __ Bind(&falsePath); | 4926 __ Bind(&falsePath); |
| 4942 __ movl(Address(ESP, 4), Immediate(0x0)); | 4927 __ movl(Address(ESP, 4), Immediate(0x0)); |
| 4943 break; | 4928 break; |
| 4944 case MethodRecognizer::kInt32x4WithFlagZ: | 4929 case MethodRecognizer::kInt32x4WithFlagZ: |
| 4945 __ movl(Address(ESP, 8), Immediate(0xFFFFFFFF)); | 4930 __ movl(Address(ESP, 8), Immediate(0xFFFFFFFF)); |
| 4946 __ jmp(&exitPath); | 4931 __ jmp(&exitPath); |
| 4947 __ Bind(&falsePath); | 4932 __ Bind(&falsePath); |
| 4948 __ movl(Address(ESP, 8), Immediate(0x0)); | 4933 __ movl(Address(ESP, 8), Immediate(0x0)); |
| 4949 break; | 4934 break; |
| 4950 case MethodRecognizer::kInt32x4WithFlagW: | 4935 case MethodRecognizer::kInt32x4WithFlagW: |
| 4951 __ movl(Address(ESP, 12), Immediate(0xFFFFFFFF)); | 4936 __ movl(Address(ESP, 12), Immediate(0xFFFFFFFF)); |
| 4952 __ jmp(&exitPath); | 4937 __ jmp(&exitPath); |
| 4953 __ Bind(&falsePath); | 4938 __ Bind(&falsePath); |
| 4954 __ movl(Address(ESP, 12), Immediate(0x0)); | 4939 __ movl(Address(ESP, 12), Immediate(0x0)); |
| 4955 break; | 4940 break; |
| 4956 default: UNREACHABLE(); | 4941 default: |
| 4942 UNREACHABLE(); |
| 4957 } | 4943 } |
| 4958 __ Bind(&exitPath); | 4944 __ Bind(&exitPath); |
| 4959 // Copy mask back to register. | 4945 // Copy mask back to register. |
| 4960 __ movups(mask, Address(ESP, 0)); | 4946 __ movups(mask, Address(ESP, 0)); |
| 4961 __ addl(ESP, Immediate(16)); | 4947 __ addl(ESP, Immediate(16)); |
| 4962 } | 4948 } |
| 4963 | 4949 |
| 4964 | 4950 |
| 4965 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4951 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
| 4966 bool opt) const { | 4952 bool opt) const { |
| 4967 const intptr_t kNumInputs = 1; | 4953 const intptr_t kNumInputs = 1; |
| 4968 const intptr_t kNumTemps = 0; | 4954 const intptr_t kNumTemps = 0; |
| 4969 LocationSummary* summary = new(zone) LocationSummary( | 4955 LocationSummary* summary = new (zone) |
| 4970 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4956 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4971 summary->set_in(0, Location::RequiresFpuRegister()); | 4957 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4972 summary->set_out(0, Location::SameAsFirstInput()); | 4958 summary->set_out(0, Location::SameAsFirstInput()); |
| 4973 return summary; | 4959 return summary; |
| 4974 } | 4960 } |
| 4975 | 4961 |
| 4976 | 4962 |
| 4977 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4963 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4978 // NOP. | 4964 // NOP. |
| 4979 } | 4965 } |
| 4980 | 4966 |
| 4981 | 4967 |
| 4982 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 4968 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 4983 bool opt) const { | 4969 bool opt) const { |
| 4984 const intptr_t kNumInputs = 2; | 4970 const intptr_t kNumInputs = 2; |
| 4985 const intptr_t kNumTemps = 0; | 4971 const intptr_t kNumTemps = 0; |
| 4986 LocationSummary* summary = new(zone) LocationSummary( | 4972 LocationSummary* summary = new (zone) |
| 4987 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4973 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4988 summary->set_in(0, Location::RequiresFpuRegister()); | 4974 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4989 summary->set_in(1, Location::RequiresFpuRegister()); | 4975 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4990 summary->set_out(0, Location::SameAsFirstInput()); | 4976 summary->set_out(0, Location::SameAsFirstInput()); |
| 4991 return summary; | 4977 return summary; |
| 4992 } | 4978 } |
| 4993 | 4979 |
| 4994 | 4980 |
| 4995 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4981 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4996 XmmRegister left = locs()->in(0).fpu_reg(); | 4982 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4997 XmmRegister right = locs()->in(1).fpu_reg(); | 4983 XmmRegister right = locs()->in(1).fpu_reg(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5008 case Token::kBIT_XOR: { | 4994 case Token::kBIT_XOR: { |
| 5009 __ xorps(left, right); | 4995 __ xorps(left, right); |
| 5010 break; | 4996 break; |
| 5011 } | 4997 } |
| 5012 case Token::kADD: | 4998 case Token::kADD: |
| 5013 __ addpl(left, right); | 4999 __ addpl(left, right); |
| 5014 break; | 5000 break; |
| 5015 case Token::kSUB: | 5001 case Token::kSUB: |
| 5016 __ subpl(left, right); | 5002 __ subpl(left, right); |
| 5017 break; | 5003 break; |
| 5018 default: UNREACHABLE(); | 5004 default: |
| 5005 UNREACHABLE(); |
| 5019 } | 5006 } |
| 5020 } | 5007 } |
| 5021 | 5008 |
| 5022 | 5009 |
| 5023 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 5010 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
| 5024 bool opt) const { | 5011 bool opt) const { |
| 5025 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 5012 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
| 5026 (kind() == MathUnaryInstr::kDoubleSquare)); | 5013 (kind() == MathUnaryInstr::kDoubleSquare)); |
| 5027 const intptr_t kNumInputs = 1; | 5014 const intptr_t kNumInputs = 1; |
| 5028 const intptr_t kNumTemps = 0; | 5015 const intptr_t kNumTemps = 0; |
| 5029 LocationSummary* summary = new(zone) LocationSummary( | 5016 LocationSummary* summary = new (zone) |
| 5030 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5017 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5031 summary->set_in(0, Location::RequiresFpuRegister()); | 5018 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5032 if (kind() == MathUnaryInstr::kDoubleSquare) { | 5019 if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 5033 summary->set_out(0, Location::SameAsFirstInput()); | 5020 summary->set_out(0, Location::SameAsFirstInput()); |
| 5034 } else { | 5021 } else { |
| 5035 summary->set_out(0, Location::RequiresFpuRegister()); | 5022 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5036 } | 5023 } |
| 5037 return summary; | 5024 return summary; |
| 5038 } | 5025 } |
| 5039 | 5026 |
| 5040 | 5027 |
| 5041 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5028 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5042 if (kind() == MathUnaryInstr::kSqrt) { | 5029 if (kind() == MathUnaryInstr::kSqrt) { |
| 5043 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5030 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 5044 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 5031 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 5045 XmmRegister value_reg = locs()->in(0).fpu_reg(); | 5032 XmmRegister value_reg = locs()->in(0).fpu_reg(); |
| 5046 __ mulsd(value_reg, value_reg); | 5033 __ mulsd(value_reg, value_reg); |
| 5047 ASSERT(value_reg == locs()->out(0).fpu_reg()); | 5034 ASSERT(value_reg == locs()->out(0).fpu_reg()); |
| 5048 } else { | 5035 } else { |
| 5049 UNREACHABLE(); | 5036 UNREACHABLE(); |
| 5050 } | 5037 } |
| 5051 } | 5038 } |
| 5052 | 5039 |
| 5053 | 5040 |
| 5054 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 5041 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
| 5055 Zone* zone, bool opt) const { | 5042 Zone* zone, |
| 5043 bool opt) const { |
| 5056 const intptr_t kNumTemps = 0; | 5044 const intptr_t kNumTemps = 0; |
| 5057 LocationSummary* summary = new(zone) LocationSummary( | 5045 LocationSummary* summary = new (zone) |
| 5058 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5046 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5059 summary->set_in(0, Location::RegisterLocation(EAX)); | 5047 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 5060 summary->set_in(1, Location::RegisterLocation(ECX)); | 5048 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 5061 summary->set_in(2, Location::RegisterLocation(EDX)); | 5049 summary->set_in(2, Location::RegisterLocation(EDX)); |
| 5062 summary->set_in(3, Location::RegisterLocation(EBX)); | 5050 summary->set_in(3, Location::RegisterLocation(EBX)); |
| 5063 summary->set_out(0, Location::RegisterLocation(EAX)); | 5051 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 5064 return summary; | 5052 return summary; |
| 5065 } | 5053 } |
| 5066 | 5054 |
| 5067 | 5055 |
| 5068 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 5056 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
| 5069 FlowGraphCompiler* compiler) { | 5057 FlowGraphCompiler* compiler) { |
| 5070 | |
| 5071 // Save ESP. EDI is chosen because it is callee saved so we do not need to | 5058 // Save ESP. EDI is chosen because it is callee saved so we do not need to |
| 5072 // back it up before calling into the runtime. | 5059 // back it up before calling into the runtime. |
| 5073 static const Register kSavedSPReg = EDI; | 5060 static const Register kSavedSPReg = EDI; |
| 5074 __ movl(kSavedSPReg, ESP); | 5061 __ movl(kSavedSPReg, ESP); |
| 5075 __ ReserveAlignedFrameSpace(kWordSize * TargetFunction().argument_count()); | 5062 __ ReserveAlignedFrameSpace(kWordSize * TargetFunction().argument_count()); |
| 5076 | 5063 |
| 5077 __ movl(Address(ESP, + 0 * kWordSize), locs()->in(0).reg()); | 5064 __ movl(Address(ESP, +0 * kWordSize), locs()->in(0).reg()); |
| 5078 __ movl(Address(ESP, + 1 * kWordSize), locs()->in(1).reg()); | 5065 __ movl(Address(ESP, +1 * kWordSize), locs()->in(1).reg()); |
| 5079 __ movl(Address(ESP, + 2 * kWordSize), locs()->in(2).reg()); | 5066 __ movl(Address(ESP, +2 * kWordSize), locs()->in(2).reg()); |
| 5080 __ movl(Address(ESP, + 3 * kWordSize), locs()->in(3).reg()); | 5067 __ movl(Address(ESP, +3 * kWordSize), locs()->in(3).reg()); |
| 5081 | 5068 |
| 5082 // Call the function. | 5069 // Call the function. |
| 5083 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 5070 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
| 5084 | 5071 |
| 5085 // Restore ESP. | 5072 // Restore ESP. |
| 5086 __ movl(ESP, kSavedSPReg); | 5073 __ movl(ESP, kSavedSPReg); |
| 5087 } | 5074 } |
| 5088 | 5075 |
| 5089 | 5076 |
| 5090 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 5077 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
| 5091 bool opt) const { | 5078 bool opt) const { |
| 5092 if (result_cid() == kDoubleCid) { | 5079 if (result_cid() == kDoubleCid) { |
| 5093 const intptr_t kNumInputs = 2; | 5080 const intptr_t kNumInputs = 2; |
| 5094 const intptr_t kNumTemps = 1; | 5081 const intptr_t kNumTemps = 1; |
| 5095 LocationSummary* summary = new(zone) LocationSummary( | 5082 LocationSummary* summary = new (zone) |
| 5096 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5083 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5097 summary->set_in(0, Location::RequiresFpuRegister()); | 5084 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5098 summary->set_in(1, Location::RequiresFpuRegister()); | 5085 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5099 // Reuse the left register so that code can be made shorter. | 5086 // Reuse the left register so that code can be made shorter. |
| 5100 summary->set_out(0, Location::SameAsFirstInput()); | 5087 summary->set_out(0, Location::SameAsFirstInput()); |
| 5101 summary->set_temp(0, Location::RequiresRegister()); | 5088 summary->set_temp(0, Location::RequiresRegister()); |
| 5102 return summary; | 5089 return summary; |
| 5103 } | 5090 } |
| 5104 | 5091 |
| 5105 ASSERT(result_cid() == kSmiCid); | 5092 ASSERT(result_cid() == kSmiCid); |
| 5106 const intptr_t kNumInputs = 2; | 5093 const intptr_t kNumInputs = 2; |
| 5107 const intptr_t kNumTemps = 0; | 5094 const intptr_t kNumTemps = 0; |
| 5108 LocationSummary* summary = new(zone) LocationSummary( | 5095 LocationSummary* summary = new (zone) |
| 5109 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5096 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5110 summary->set_in(0, Location::RequiresRegister()); | 5097 summary->set_in(0, Location::RequiresRegister()); |
| 5111 summary->set_in(1, Location::RequiresRegister()); | 5098 summary->set_in(1, Location::RequiresRegister()); |
| 5112 // Reuse the left register so that code can be made shorter. | 5099 // Reuse the left register so that code can be made shorter. |
| 5113 summary->set_out(0, Location::SameAsFirstInput()); | 5100 summary->set_out(0, Location::SameAsFirstInput()); |
| 5114 return summary; | 5101 return summary; |
| 5115 } | 5102 } |
| 5116 | 5103 |
| 5117 | 5104 |
| 5118 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5105 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5119 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 5106 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5172 __ cmovgel(result, right); | 5159 __ cmovgel(result, right); |
| 5173 } else { | 5160 } else { |
| 5174 __ cmovlessl(result, right); | 5161 __ cmovlessl(result, right); |
| 5175 } | 5162 } |
| 5176 } | 5163 } |
| 5177 | 5164 |
| 5178 | 5165 |
| 5179 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 5166 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 5180 bool opt) const { | 5167 bool opt) const { |
| 5181 const intptr_t kNumInputs = 1; | 5168 const intptr_t kNumInputs = 1; |
| 5182 return LocationSummary::Make(zone, | 5169 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
| 5183 kNumInputs, | |
| 5184 Location::SameAsFirstInput(), | |
| 5185 LocationSummary::kNoCall); | 5170 LocationSummary::kNoCall); |
| 5186 } | 5171 } |
| 5187 | 5172 |
| 5188 | 5173 |
| 5189 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5174 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5190 Register value = locs()->in(0).reg(); | 5175 Register value = locs()->in(0).reg(); |
| 5191 ASSERT(value == locs()->out(0).reg()); | 5176 ASSERT(value == locs()->out(0).reg()); |
| 5192 switch (op_kind()) { | 5177 switch (op_kind()) { |
| 5193 case Token::kNEGATE: { | 5178 case Token::kNEGATE: { |
| 5194 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 5179 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
| 5195 __ negl(value); | 5180 __ negl(value); |
| 5196 __ j(OVERFLOW, deopt); | 5181 __ j(OVERFLOW, deopt); |
| 5197 break; | 5182 break; |
| 5198 } | 5183 } |
| 5199 case Token::kBIT_NOT: | 5184 case Token::kBIT_NOT: |
| 5200 __ notl(value); | 5185 __ notl(value); |
| 5201 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 5186 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
| 5202 break; | 5187 break; |
| 5203 default: | 5188 default: |
| 5204 UNREACHABLE(); | 5189 UNREACHABLE(); |
| 5205 } | 5190 } |
| 5206 } | 5191 } |
| 5207 | 5192 |
| 5208 | 5193 |
| 5209 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 5194 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 5210 bool opt) const { | 5195 bool opt) const { |
| 5211 const intptr_t kNumInputs = 1; | 5196 const intptr_t kNumInputs = 1; |
| 5212 const intptr_t kNumTemps = 0; | 5197 const intptr_t kNumTemps = 0; |
| 5213 LocationSummary* summary = new(zone) LocationSummary( | 5198 LocationSummary* summary = new (zone) |
| 5214 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5199 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5215 summary->set_in(0, Location::RequiresFpuRegister()); | 5200 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5216 summary->set_out(0, Location::SameAsFirstInput()); | 5201 summary->set_out(0, Location::SameAsFirstInput()); |
| 5217 return summary; | 5202 return summary; |
| 5218 } | 5203 } |
| 5219 | 5204 |
| 5220 | 5205 |
| 5221 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5206 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5222 XmmRegister value = locs()->in(0).fpu_reg(); | 5207 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5223 ASSERT(locs()->out(0).fpu_reg() == value); | 5208 ASSERT(locs()->out(0).fpu_reg() == value); |
| 5224 __ DoubleNegate(value); | 5209 __ DoubleNegate(value); |
| 5225 } | 5210 } |
| 5226 | 5211 |
| 5227 | 5212 |
| 5228 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 5213 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5229 bool opt) const { | 5214 bool opt) const { |
| 5230 const intptr_t kNumInputs = 1; | 5215 const intptr_t kNumInputs = 1; |
| 5231 const intptr_t kNumTemps = 0; | 5216 const intptr_t kNumTemps = 0; |
| 5232 LocationSummary* result = new(zone) LocationSummary( | 5217 LocationSummary* result = new (zone) |
| 5233 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5218 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5234 result->set_in(0, Location::RequiresRegister()); | 5219 result->set_in(0, Location::RequiresRegister()); |
| 5235 result->set_out(0, Location::RequiresFpuRegister()); | 5220 result->set_out(0, Location::RequiresFpuRegister()); |
| 5236 return result; | 5221 return result; |
| 5237 } | 5222 } |
| 5238 | 5223 |
| 5239 | 5224 |
| 5240 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5225 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5241 Register value = locs()->in(0).reg(); | 5226 Register value = locs()->in(0).reg(); |
| 5242 FpuRegister result = locs()->out(0).fpu_reg(); | 5227 FpuRegister result = locs()->out(0).fpu_reg(); |
| 5243 __ cvtsi2sd(result, value); | 5228 __ cvtsi2sd(result, value); |
| 5244 } | 5229 } |
| 5245 | 5230 |
| 5246 | 5231 |
| 5247 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 5232 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5248 bool opt) const { | 5233 bool opt) const { |
| 5249 const intptr_t kNumInputs = 1; | 5234 const intptr_t kNumInputs = 1; |
| 5250 const intptr_t kNumTemps = 0; | 5235 const intptr_t kNumTemps = 0; |
| 5251 LocationSummary* result = new(zone) LocationSummary( | 5236 LocationSummary* result = new (zone) |
| 5252 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5237 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5253 result->set_in(0, Location::WritableRegister()); | 5238 result->set_in(0, Location::WritableRegister()); |
| 5254 result->set_out(0, Location::RequiresFpuRegister()); | 5239 result->set_out(0, Location::RequiresFpuRegister()); |
| 5255 return result; | 5240 return result; |
| 5256 } | 5241 } |
| 5257 | 5242 |
| 5258 | 5243 |
| 5259 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5244 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5260 Register value = locs()->in(0).reg(); | 5245 Register value = locs()->in(0).reg(); |
| 5261 FpuRegister result = locs()->out(0).fpu_reg(); | 5246 FpuRegister result = locs()->out(0).fpu_reg(); |
| 5262 __ SmiUntag(value); | 5247 __ SmiUntag(value); |
| 5263 __ cvtsi2sd(result, value); | 5248 __ cvtsi2sd(result, value); |
| 5264 } | 5249 } |
| 5265 | 5250 |
| 5266 | 5251 |
| 5267 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, | 5252 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5268 bool opt) const { | 5253 bool opt) const { |
| 5269 const intptr_t kNumInputs = 1; | 5254 const intptr_t kNumInputs = 1; |
| 5270 const intptr_t kNumTemps = 0; | 5255 const intptr_t kNumTemps = 0; |
| 5271 LocationSummary* result = new(zone) LocationSummary( | 5256 LocationSummary* result = new (zone) |
| 5272 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5257 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5273 result->set_in(0, Location::Pair(Location::RequiresRegister(), | 5258 result->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5274 Location::RequiresRegister())); | 5259 Location::RequiresRegister())); |
| 5275 result->set_out(0, Location::RequiresFpuRegister()); | 5260 result->set_out(0, Location::RequiresFpuRegister()); |
| 5276 return result; | 5261 return result; |
| 5277 } | 5262 } |
| 5278 | 5263 |
| 5279 | 5264 |
| 5280 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5265 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5281 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5266 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 5282 Register in_lo = pair->At(0).reg(); | 5267 Register in_lo = pair->At(0).reg(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5296 __ movsd(result, Address(ESP, 0)); | 5281 __ movsd(result, Address(ESP, 0)); |
| 5297 // Pop args. | 5282 // Pop args. |
| 5298 __ addl(ESP, Immediate(2 * kWordSize)); | 5283 __ addl(ESP, Immediate(2 * kWordSize)); |
| 5299 } | 5284 } |
| 5300 | 5285 |
| 5301 | 5286 |
| 5302 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 5287 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
| 5303 bool opt) const { | 5288 bool opt) const { |
| 5304 const intptr_t kNumInputs = 1; | 5289 const intptr_t kNumInputs = 1; |
| 5305 const intptr_t kNumTemps = 0; | 5290 const intptr_t kNumTemps = 0; |
| 5306 LocationSummary* result = new(zone) LocationSummary( | 5291 LocationSummary* result = new (zone) |
| 5307 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5292 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5308 result->set_in(0, Location::RegisterLocation(ECX)); | 5293 result->set_in(0, Location::RegisterLocation(ECX)); |
| 5309 result->set_out(0, Location::RegisterLocation(EAX)); | 5294 result->set_out(0, Location::RegisterLocation(EAX)); |
| 5310 return result; | 5295 return result; |
| 5311 } | 5296 } |
| 5312 | 5297 |
| 5313 | 5298 |
| 5314 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5299 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5315 Register result = locs()->out(0).reg(); | 5300 Register result = locs()->out(0).reg(); |
| 5316 Register value_obj = locs()->in(0).reg(); | 5301 Register value_obj = locs()->in(0).reg(); |
| 5317 XmmRegister value_double = XMM0; | 5302 XmmRegister value_double = XMM0; |
| 5318 ASSERT(result == EAX); | 5303 ASSERT(result == EAX); |
| 5319 ASSERT(result != value_obj); | 5304 ASSERT(result != value_obj); |
| 5320 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); | 5305 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); |
| 5321 __ cvttsd2si(result, value_double); | 5306 __ cvttsd2si(result, value_double); |
| 5322 // Overflow is signalled with minint. | 5307 // Overflow is signalled with minint. |
| 5323 Label do_call, done; | 5308 Label do_call, done; |
| 5324 // Check for overflow and that it fits into Smi. | 5309 // Check for overflow and that it fits into Smi. |
| 5325 __ cmpl(result, Immediate(0xC0000000)); | 5310 __ cmpl(result, Immediate(0xC0000000)); |
| 5326 __ j(NEGATIVE, &do_call, Assembler::kNearJump); | 5311 __ j(NEGATIVE, &do_call, Assembler::kNearJump); |
| 5327 __ SmiTag(result); | 5312 __ SmiTag(result); |
| 5328 __ jmp(&done); | 5313 __ jmp(&done); |
| 5329 __ Bind(&do_call); | 5314 __ Bind(&do_call); |
| 5330 __ pushl(value_obj); | 5315 __ pushl(value_obj); |
| 5331 ASSERT(instance_call()->HasICData()); | 5316 ASSERT(instance_call()->HasICData()); |
| 5332 const ICData& ic_data = *instance_call()->ic_data(); | 5317 const ICData& ic_data = *instance_call()->ic_data(); |
| 5333 ASSERT((ic_data.NumberOfChecks() == 1)); | 5318 ASSERT((ic_data.NumberOfChecks() == 1)); |
| 5334 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 5319 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 5335 | 5320 |
| 5336 const intptr_t kNumberOfArguments = 1; | 5321 const intptr_t kNumberOfArguments = 1; |
| 5337 compiler->GenerateStaticCall(deopt_id(), | 5322 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
| 5338 instance_call()->token_pos(), | |
| 5339 target, | |
| 5340 kNumberOfArguments, | 5323 kNumberOfArguments, |
| 5341 Object::null_array(), // No argument names. | 5324 Object::null_array(), // No argument names. |
| 5342 locs(), | 5325 locs(), ICData::Handle()); |
| 5343 ICData::Handle()); | |
| 5344 __ Bind(&done); | 5326 __ Bind(&done); |
| 5345 } | 5327 } |
| 5346 | 5328 |
| 5347 | 5329 |
| 5348 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5330 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
| 5349 bool opt) const { | 5331 bool opt) const { |
| 5350 const intptr_t kNumInputs = 1; | 5332 const intptr_t kNumInputs = 1; |
| 5351 const intptr_t kNumTemps = 0; | 5333 const intptr_t kNumTemps = 0; |
| 5352 LocationSummary* result = new(zone) LocationSummary( | 5334 LocationSummary* result = new (zone) |
| 5353 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5335 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5354 result->set_in(0, Location::RequiresFpuRegister()); | 5336 result->set_in(0, Location::RequiresFpuRegister()); |
| 5355 result->set_out(0, Location::RequiresRegister()); | 5337 result->set_out(0, Location::RequiresRegister()); |
| 5356 return result; | 5338 return result; |
| 5357 } | 5339 } |
| 5358 | 5340 |
| 5359 | 5341 |
| 5360 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5342 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5361 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5343 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
| 5362 Register result = locs()->out(0).reg(); | 5344 Register result = locs()->out(0).reg(); |
| 5363 XmmRegister value = locs()->in(0).fpu_reg(); | 5345 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5364 __ cvttsd2si(result, value); | 5346 __ cvttsd2si(result, value); |
| 5365 // Check for overflow and that it fits into Smi. | 5347 // Check for overflow and that it fits into Smi. |
| 5366 __ cmpl(result, Immediate(0xC0000000)); | 5348 __ cmpl(result, Immediate(0xC0000000)); |
| 5367 __ j(NEGATIVE, deopt); | 5349 __ j(NEGATIVE, deopt); |
| 5368 __ SmiTag(result); | 5350 __ SmiTag(result); |
| 5369 } | 5351 } |
| 5370 | 5352 |
| 5371 | 5353 |
| 5372 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, | 5354 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5373 bool opt) const { | 5355 bool opt) const { |
| 5374 const intptr_t kNumInputs = 1; | 5356 const intptr_t kNumInputs = 1; |
| 5375 const intptr_t kNumTemps = 0; | 5357 const intptr_t kNumTemps = 0; |
| 5376 LocationSummary* result = new(zone) LocationSummary( | 5358 LocationSummary* result = new (zone) |
| 5377 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5359 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5378 result->set_in(0, Location::RequiresFpuRegister()); | 5360 result->set_in(0, Location::RequiresFpuRegister()); |
| 5379 result->set_out(0, Location::RequiresFpuRegister()); | 5361 result->set_out(0, Location::RequiresFpuRegister()); |
| 5380 return result; | 5362 return result; |
| 5381 } | 5363 } |
| 5382 | 5364 |
| 5383 | 5365 |
| 5384 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5366 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5385 XmmRegister value = locs()->in(0).fpu_reg(); | 5367 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5386 XmmRegister result = locs()->out(0).fpu_reg(); | 5368 XmmRegister result = locs()->out(0).fpu_reg(); |
| 5387 switch (recognized_kind()) { | 5369 switch (recognized_kind()) { |
| 5388 case MethodRecognizer::kDoubleTruncate: | 5370 case MethodRecognizer::kDoubleTruncate: |
| 5389 __ roundsd(result, value, Assembler::kRoundToZero); | 5371 __ roundsd(result, value, Assembler::kRoundToZero); |
| 5390 break; | 5372 break; |
| 5391 case MethodRecognizer::kDoubleFloor: | 5373 case MethodRecognizer::kDoubleFloor: |
| 5392 __ roundsd(result, value, Assembler::kRoundDown); | 5374 __ roundsd(result, value, Assembler::kRoundDown); |
| 5393 break; | 5375 break; |
| 5394 case MethodRecognizer::kDoubleCeil: | 5376 case MethodRecognizer::kDoubleCeil: |
| 5395 __ roundsd(result, value, Assembler::kRoundUp); | 5377 __ roundsd(result, value, Assembler::kRoundUp); |
| 5396 break; | 5378 break; |
| 5397 default: | 5379 default: |
| 5398 UNREACHABLE(); | 5380 UNREACHABLE(); |
| 5399 } | 5381 } |
| 5400 } | 5382 } |
| 5401 | 5383 |
| 5402 | 5384 |
| 5403 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5385 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
| 5404 bool opt) const { | 5386 bool opt) const { |
| 5405 const intptr_t kNumInputs = 1; | 5387 const intptr_t kNumInputs = 1; |
| 5406 const intptr_t kNumTemps = 0; | 5388 const intptr_t kNumTemps = 0; |
| 5407 LocationSummary* result = new(zone) LocationSummary( | 5389 LocationSummary* result = new (zone) |
| 5408 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5390 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5409 result->set_in(0, Location::RequiresFpuRegister()); | 5391 result->set_in(0, Location::RequiresFpuRegister()); |
| 5410 result->set_out(0, Location::SameAsFirstInput()); | 5392 result->set_out(0, Location::SameAsFirstInput()); |
| 5411 return result; | 5393 return result; |
| 5412 } | 5394 } |
| 5413 | 5395 |
| 5414 | 5396 |
| 5415 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5397 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5416 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5398 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 5417 } | 5399 } |
| 5418 | 5400 |
| 5419 | 5401 |
| 5420 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5402 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5421 bool opt) const { | 5403 bool opt) const { |
| 5422 const intptr_t kNumInputs = 1; | 5404 const intptr_t kNumInputs = 1; |
| 5423 const intptr_t kNumTemps = 0; | 5405 const intptr_t kNumTemps = 0; |
| 5424 LocationSummary* result = new(zone) LocationSummary( | 5406 LocationSummary* result = new (zone) |
| 5425 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5407 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5426 result->set_in(0, Location::RequiresFpuRegister()); | 5408 result->set_in(0, Location::RequiresFpuRegister()); |
| 5427 result->set_out(0, Location::SameAsFirstInput()); | 5409 result->set_out(0, Location::SameAsFirstInput()); |
| 5428 return result; | 5410 return result; |
| 5429 } | 5411 } |
| 5430 | 5412 |
| 5431 | 5413 |
| 5432 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5414 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5433 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5415 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 5434 } | 5416 } |
| 5435 | 5417 |
| 5436 | 5418 |
| 5437 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5419 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
| 5438 bool opt) const { | 5420 bool opt) const { |
| 5439 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5421 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 5440 const intptr_t kNumTemps = | 5422 const intptr_t kNumTemps = |
| 5441 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; | 5423 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; |
| 5442 LocationSummary* result = new(zone) LocationSummary( | 5424 LocationSummary* result = new (zone) |
| 5443 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5425 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5444 // EDI is chosen because it is callee saved so we do not need to back it | 5426 // EDI is chosen because it is callee saved so we do not need to back it |
| 5445 // up before calling into the runtime. | 5427 // up before calling into the runtime. |
| 5446 result->set_temp(0, Location::RegisterLocation(EDI)); | 5428 result->set_temp(0, Location::RegisterLocation(EDI)); |
| 5447 result->set_in(0, Location::FpuRegisterLocation(XMM1)); | 5429 result->set_in(0, Location::FpuRegisterLocation(XMM1)); |
| 5448 if (InputCount() == 2) { | 5430 if (InputCount() == 2) { |
| 5449 result->set_in(1, Location::FpuRegisterLocation(XMM2)); | 5431 result->set_in(1, Location::FpuRegisterLocation(XMM2)); |
| 5450 } | 5432 } |
| 5451 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5433 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5452 // Temp index 1. | 5434 // Temp index 1. |
| 5453 result->set_temp(1, Location::RegisterLocation(EAX)); | 5435 result->set_temp(1, Location::RegisterLocation(EAX)); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 5481 ASSERT(instr->InputCount() == kInputCount); | 5463 ASSERT(instr->InputCount() == kInputCount); |
| 5482 LocationSummary* locs = instr->locs(); | 5464 LocationSummary* locs = instr->locs(); |
| 5483 | 5465 |
| 5484 XmmRegister base = locs->in(0).fpu_reg(); | 5466 XmmRegister base = locs->in(0).fpu_reg(); |
| 5485 XmmRegister exp = locs->in(1).fpu_reg(); | 5467 XmmRegister exp = locs->in(1).fpu_reg(); |
| 5486 XmmRegister result = locs->out(0).fpu_reg(); | 5468 XmmRegister result = locs->out(0).fpu_reg(); |
| 5487 Register temp = locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg(); | 5469 Register temp = locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg(); |
| 5488 XmmRegister zero_temp = | 5470 XmmRegister zero_temp = |
| 5489 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg(); | 5471 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg(); |
| 5490 | 5472 |
| 5491 __ xorps(zero_temp, zero_temp); // 0.0. | 5473 __ xorps(zero_temp, zero_temp); // 0.0. |
| 5492 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1.0))); | 5474 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1.0))); |
| 5493 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5475 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 5494 | 5476 |
| 5495 Label check_base, skip_call; | 5477 Label check_base, skip_call; |
| 5496 // exponent == 0.0 -> return 1.0; | 5478 // exponent == 0.0 -> return 1.0; |
| 5497 __ comisd(exp, zero_temp); | 5479 __ comisd(exp, zero_temp); |
| 5498 __ j(PARITY_EVEN, &check_base); | 5480 __ j(PARITY_EVEN, &check_base); |
| 5499 __ j(EQUAL, &skip_call); // 'result' is 1.0. | 5481 __ j(EQUAL, &skip_call); // 'result' is 1.0. |
| 5500 | 5482 |
| 5501 // exponent == 1.0 ? | 5483 // exponent == 1.0 ? |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5610 // Restore ESP. | 5592 // Restore ESP. |
| 5611 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); | 5593 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); |
| 5612 } | 5594 } |
| 5613 | 5595 |
| 5614 | 5596 |
| 5615 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 5597 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
| 5616 bool opt) const { | 5598 bool opt) const { |
| 5617 // Only use this instruction in optimized code. | 5599 // Only use this instruction in optimized code. |
| 5618 ASSERT(opt); | 5600 ASSERT(opt); |
| 5619 const intptr_t kNumInputs = 1; | 5601 const intptr_t kNumInputs = 1; |
| 5620 LocationSummary* summary = new(zone) LocationSummary( | 5602 LocationSummary* summary = |
| 5621 zone, kNumInputs, 0, LocationSummary::kNoCall); | 5603 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 5622 if (representation() == kUnboxedDouble) { | 5604 if (representation() == kUnboxedDouble) { |
| 5623 if (index() == 0) { | 5605 if (index() == 0) { |
| 5624 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | 5606 summary->set_in( |
| 5625 Location::Any())); | 5607 0, Location::Pair(Location::RequiresFpuRegister(), Location::Any())); |
| 5626 } else { | 5608 } else { |
| 5627 ASSERT(index() == 1); | 5609 ASSERT(index() == 1); |
| 5628 summary->set_in(0, Location::Pair(Location::Any(), | 5610 summary->set_in( |
| 5629 Location::RequiresFpuRegister())); | 5611 0, Location::Pair(Location::Any(), Location::RequiresFpuRegister())); |
| 5630 } | 5612 } |
| 5631 summary->set_out(0, Location::RequiresFpuRegister()); | 5613 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5632 } else { | 5614 } else { |
| 5633 ASSERT(representation() == kTagged); | 5615 ASSERT(representation() == kTagged); |
| 5634 if (index() == 0) { | 5616 if (index() == 0) { |
| 5635 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5617 summary->set_in( |
| 5636 Location::Any())); | 5618 0, Location::Pair(Location::RequiresRegister(), Location::Any())); |
| 5637 } else { | 5619 } else { |
| 5638 ASSERT(index() == 1); | 5620 ASSERT(index() == 1); |
| 5639 summary->set_in(0, Location::Pair(Location::Any(), | 5621 summary->set_in( |
| 5640 Location::RequiresRegister())); | 5622 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
| 5641 } | 5623 } |
| 5642 summary->set_out(0, Location::RequiresRegister()); | 5624 summary->set_out(0, Location::RequiresRegister()); |
| 5643 } | 5625 } |
| 5644 return summary; | 5626 return summary; |
| 5645 } | 5627 } |
| 5646 | 5628 |
| 5647 | 5629 |
| 5648 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5630 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5649 ASSERT(locs()->in(0).IsPairLocation()); | 5631 ASSERT(locs()->in(0).IsPairLocation()); |
| 5650 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5632 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 5651 Location in_loc = pair->At(index()); | 5633 Location in_loc = pair->At(index()); |
| 5652 if (representation() == kUnboxedDouble) { | 5634 if (representation() == kUnboxedDouble) { |
| 5653 XmmRegister out = locs()->out(0).fpu_reg(); | 5635 XmmRegister out = locs()->out(0).fpu_reg(); |
| 5654 XmmRegister in = in_loc.fpu_reg(); | 5636 XmmRegister in = in_loc.fpu_reg(); |
| 5655 __ movaps(out, in); | 5637 __ movaps(out, in); |
| 5656 } else { | 5638 } else { |
| 5657 ASSERT(representation() == kTagged); | 5639 ASSERT(representation() == kTagged); |
| 5658 Register out = locs()->out(0).reg(); | 5640 Register out = locs()->out(0).reg(); |
| 5659 Register in = in_loc.reg(); | 5641 Register in = in_loc.reg(); |
| 5660 __ movl(out, in); | 5642 __ movl(out, in); |
| 5661 } | 5643 } |
| 5662 } | 5644 } |
| 5663 | 5645 |
| 5664 | 5646 |
| 5665 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 5647 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, |
| 5666 bool opt) const { | 5648 bool opt) const { |
| 5667 if (kind() == MergedMathInstr::kTruncDivMod) { | 5649 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 5668 const intptr_t kNumInputs = 2; | 5650 const intptr_t kNumInputs = 2; |
| 5669 const intptr_t kNumTemps = 0; | 5651 const intptr_t kNumTemps = 0; |
| 5670 LocationSummary* summary = new(zone) LocationSummary( | 5652 LocationSummary* summary = new (zone) |
| 5671 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5653 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5672 // Both inputs must be writable because they will be untagged. | 5654 // Both inputs must be writable because they will be untagged. |
| 5673 summary->set_in(0, Location::RegisterLocation(EAX)); | 5655 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 5674 summary->set_in(1, Location::WritableRegister()); | 5656 summary->set_in(1, Location::WritableRegister()); |
| 5675 // Output is a pair of registers. | 5657 // Output is a pair of registers. |
| 5676 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 5658 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
| 5677 Location::RegisterLocation(EDX))); | 5659 Location::RegisterLocation(EDX))); |
| 5678 return summary; | 5660 return summary; |
| 5679 } | 5661 } |
| 5680 if (kind() == MergedMathInstr::kSinCos) { | 5662 if (kind() == MergedMathInstr::kSinCos) { |
| 5681 const intptr_t kNumInputs = 1; | 5663 const intptr_t kNumInputs = 1; |
| 5682 const intptr_t kNumTemps = 2; | 5664 const intptr_t kNumTemps = 2; |
| 5683 LocationSummary* summary = new(zone) LocationSummary( | 5665 LocationSummary* summary = new (zone) |
| 5684 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5685 // Because we always call into the runtime (LocationSummary::kCall) we | 5667 // Because we always call into the runtime (LocationSummary::kCall) we |
| 5686 // must specify each input, temp, and output register explicitly. | 5668 // must specify each input, temp, and output register explicitly. |
| 5687 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 5669 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); |
| 5688 // EDI is chosen because it is callee saved so we do not need to back it | 5670 // EDI is chosen because it is callee saved so we do not need to back it |
| 5689 // up before calling into the runtime. | 5671 // up before calling into the runtime. |
| 5690 summary->set_temp(0, Location::RegisterLocation(EDI)); | 5672 summary->set_temp(0, Location::RegisterLocation(EDI)); |
| 5691 summary->set_temp(1, Location::RegisterLocation(EBX)); | 5673 summary->set_temp(1, Location::RegisterLocation(EBX)); |
| 5692 summary->set_out(0, Location::Pair(Location::FpuRegisterLocation(XMM2), | 5674 summary->set_out(0, Location::Pair(Location::FpuRegisterLocation(XMM2), |
| 5693 Location::FpuRegisterLocation(XMM3))); | 5675 Location::FpuRegisterLocation(XMM3))); |
| 5694 return summary; | 5676 return summary; |
| 5695 } | 5677 } |
| 5696 UNIMPLEMENTED(); | 5678 UNIMPLEMENTED(); |
| 5697 return NULL; | 5679 return NULL; |
| 5698 } | 5680 } |
| 5699 | 5681 |
| 5700 | 5682 |
| 5701 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); | 5683 typedef void (*SinCosCFunction)(double x, double* res_sin, double* res_cos); |
| 5702 | 5684 |
| 5703 extern const RuntimeEntry kSinCosRuntimeEntry( | 5685 extern const RuntimeEntry kSinCosRuntimeEntry( |
| 5704 "libc_sincos", reinterpret_cast<RuntimeFunction>( | 5686 "libc_sincos", |
| 5705 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); | 5687 reinterpret_cast<RuntimeFunction>(static_cast<SinCosCFunction>(&SinCos)), |
| 5688 1, |
| 5689 true, |
| 5690 true); |
| 5706 | 5691 |
| 5707 | 5692 |
| 5708 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5693 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5709 Label* deopt = NULL; | 5694 Label* deopt = NULL; |
| 5710 if (CanDeoptimize()) { | 5695 if (CanDeoptimize()) { |
| 5711 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5696 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
| 5712 } | 5697 } |
| 5713 | 5698 |
| 5714 if (kind() == MergedMathInstr::kTruncDivMod) { | 5699 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 5715 Register left = locs()->in(0).reg(); | 5700 Register left = locs()->in(0).reg(); |
| 5716 Register right = locs()->in(1).reg(); | 5701 Register right = locs()->in(1).reg(); |
| 5717 ASSERT(locs()->out(0).IsPairLocation()); | 5702 ASSERT(locs()->out(0).IsPairLocation()); |
| 5718 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5703 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 5719 Register result1 = pair->At(0).reg(); | 5704 Register result1 = pair->At(0).reg(); |
| 5720 Register result2 = pair->At(1).reg(); | 5705 Register result2 = pair->At(1).reg(); |
| 5721 Range* right_range = InputAt(1)->definition()->range(); | 5706 Range* right_range = InputAt(1)->definition()->range(); |
| 5722 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 5707 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 5723 // Handle divide by zero in runtime. | 5708 // Handle divide by zero in runtime. |
| 5724 __ testl(right, right); | 5709 __ testl(right, right); |
| 5725 __ j(ZERO, deopt); | 5710 __ j(ZERO, deopt); |
| 5726 } | 5711 } |
| 5727 ASSERT(left == EAX); | 5712 ASSERT(left == EAX); |
| 5728 ASSERT((right != EDX) && (right != EAX)); | 5713 ASSERT((right != EDX) && (right != EAX)); |
| 5729 ASSERT(result1 == EAX); | 5714 ASSERT(result1 == EAX); |
| 5730 ASSERT(result2 == EDX); | 5715 ASSERT(result2 == EDX); |
| 5731 __ SmiUntag(left); | 5716 __ SmiUntag(left); |
| 5732 __ SmiUntag(right); | 5717 __ SmiUntag(right); |
| 5733 __ cdq(); // Sign extend EAX -> EDX:EAX. | 5718 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 5734 __ idivl(right); // EAX: quotient, EDX: remainder. | 5719 __ idivl(right); // EAX: quotient, EDX: remainder. |
| 5735 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 5720 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 5736 // case we cannot tag the result. | 5721 // case we cannot tag the result. |
| 5737 // TODO(srdjan): We could store instead untagged intermediate results in a | 5722 // TODO(srdjan): We could store instead untagged intermediate results in a |
| 5738 // typed array, but then the load indexed instructions would need to be | 5723 // typed array, but then the load indexed instructions would need to be |
| 5739 // able to deoptimize. | 5724 // able to deoptimize. |
| 5740 __ cmpl(EAX, Immediate(0x40000000)); | 5725 __ cmpl(EAX, Immediate(0x40000000)); |
| 5741 __ j(EQUAL, deopt); | 5726 __ j(EQUAL, deopt); |
| 5742 // Modulo result (EDX) correction: | 5727 // Modulo result (EDX) correction: |
| 5743 // res = left % right; | 5728 // res = left % right; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5814 // Restore RSP. | 5799 // Restore RSP. |
| 5815 __ movl(ESP, locs()->temp(0).reg()); | 5800 __ movl(ESP, locs()->temp(0).reg()); |
| 5816 | 5801 |
| 5817 return; | 5802 return; |
| 5818 } | 5803 } |
| 5819 UNIMPLEMENTED(); | 5804 UNIMPLEMENTED(); |
| 5820 } | 5805 } |
| 5821 | 5806 |
| 5822 | 5807 |
| 5823 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5808 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
| 5824 Zone* zone, bool opt) const { | 5809 Zone* zone, |
| 5810 bool opt) const { |
| 5825 return MakeCallSummary(zone); | 5811 return MakeCallSummary(zone); |
| 5826 } | 5812 } |
| 5827 | 5813 |
| 5828 | 5814 |
| 5829 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, | 5815 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5830 bool opt) const { | |
| 5831 comparison()->InitializeLocationSummary(zone, opt); | 5816 comparison()->InitializeLocationSummary(zone, opt); |
| 5832 // Branches don't produce a result. | 5817 // Branches don't produce a result. |
| 5833 comparison()->locs()->set_out(0, Location::NoLocation()); | 5818 comparison()->locs()->set_out(0, Location::NoLocation()); |
| 5834 return comparison()->locs(); | 5819 return comparison()->locs(); |
| 5835 } | 5820 } |
| 5836 | 5821 |
| 5837 | 5822 |
| 5838 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5823 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5839 comparison()->EmitBranchCode(compiler, this); | 5824 comparison()->EmitBranchCode(compiler, this); |
| 5840 } | 5825 } |
| 5841 | 5826 |
| 5842 | 5827 |
| 5843 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5828 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
| 5844 bool opt) const { | 5829 bool opt) const { |
| 5845 const intptr_t kNumInputs = 1; | 5830 const intptr_t kNumInputs = 1; |
| 5846 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 5831 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); |
| 5847 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5832 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
| 5848 LocationSummary* summary = new(zone) LocationSummary( | 5833 LocationSummary* summary = new (zone) |
| 5849 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5834 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5850 summary->set_in(0, Location::RequiresRegister()); | 5835 summary->set_in(0, Location::RequiresRegister()); |
| 5851 if (!IsNullCheck()) { | 5836 if (!IsNullCheck()) { |
| 5852 summary->set_temp(0, Location::RequiresRegister()); | 5837 summary->set_temp(0, Location::RequiresRegister()); |
| 5853 if (need_mask_temp) { | 5838 if (need_mask_temp) { |
| 5854 summary->set_temp(1, Location::RequiresRegister()); | 5839 summary->set_temp(1, Location::RequiresRegister()); |
| 5855 } | 5840 } |
| 5856 } | 5841 } |
| 5857 return summary; | 5842 return summary; |
| 5858 } | 5843 } |
| 5859 | 5844 |
| 5860 | 5845 |
| 5861 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5846 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5862 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5847 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, |
| 5863 ICData::kDeoptCheckClass, | |
| 5864 licm_hoisted_ ? ICData::kHoisted : 0); | 5848 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5865 if (IsNullCheck()) { | 5849 if (IsNullCheck()) { |
| 5866 const Immediate& raw_null = | 5850 const Immediate& raw_null = |
| 5867 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 5851 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 5868 __ cmpl(locs()->in(0).reg(), raw_null); | 5852 __ cmpl(locs()->in(0).reg(), raw_null); |
| 5869 ASSERT(DeoptIfNull() || DeoptIfNotNull()); | 5853 ASSERT(DeoptIfNull() || DeoptIfNotNull()); |
| 5870 Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL; | 5854 Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL; |
| 5871 __ j(cond, deopt); | 5855 __ j(cond, deopt); |
| 5872 return; | 5856 return; |
| 5873 } | 5857 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5896 if (!IsDenseMask(mask)) { | 5880 if (!IsDenseMask(mask)) { |
| 5897 // Only need mask if there are missing numbers in the range. | 5881 // Only need mask if there are missing numbers in the range. |
| 5898 ASSERT(cids_.length() > 2); | 5882 ASSERT(cids_.length() > 2); |
| 5899 Register mask_reg = locs()->temp(1).reg(); | 5883 Register mask_reg = locs()->temp(1).reg(); |
| 5900 __ movl(mask_reg, Immediate(mask)); | 5884 __ movl(mask_reg, Immediate(mask)); |
| 5901 __ bt(mask_reg, temp); | 5885 __ bt(mask_reg, temp); |
| 5902 __ j(NOT_CARRY, deopt); | 5886 __ j(NOT_CARRY, deopt); |
| 5903 } | 5887 } |
| 5904 } else { | 5888 } else { |
| 5905 GrowableArray<CidTarget> sorted_ic_data; | 5889 GrowableArray<CidTarget> sorted_ic_data; |
| 5906 FlowGraphCompiler::SortICDataByCount(unary_checks(), | 5890 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, |
| 5907 &sorted_ic_data, | |
| 5908 /* drop_smi = */ true); | 5891 /* drop_smi = */ true); |
| 5909 const intptr_t num_checks = sorted_ic_data.length(); | 5892 const intptr_t num_checks = sorted_ic_data.length(); |
| 5910 const bool use_near_jump = num_checks < 5; | 5893 const bool use_near_jump = num_checks < 5; |
| 5911 for (intptr_t i = 0; i < num_checks; i++) { | 5894 for (intptr_t i = 0; i < num_checks; i++) { |
| 5912 const intptr_t cid = sorted_ic_data[i].cid; | 5895 const intptr_t cid = sorted_ic_data[i].cid; |
| 5913 ASSERT(cid != kSmiCid); | 5896 ASSERT(cid != kSmiCid); |
| 5914 __ cmpl(temp, Immediate(cid)); | 5897 __ cmpl(temp, Immediate(cid)); |
| 5915 if (i == (num_checks - 1)) { | 5898 if (i == (num_checks - 1)) { |
| 5916 __ j(NOT_EQUAL, deopt); | 5899 __ j(NOT_EQUAL, deopt); |
| 5917 } else { | 5900 } else { |
| 5918 if (use_near_jump) { | 5901 if (use_near_jump) { |
| 5919 __ j(EQUAL, &is_ok, Assembler::kNearJump); | 5902 __ j(EQUAL, &is_ok, Assembler::kNearJump); |
| 5920 } else { | 5903 } else { |
| 5921 __ j(EQUAL, &is_ok); | 5904 __ j(EQUAL, &is_ok); |
| 5922 } | 5905 } |
| 5923 } | 5906 } |
| 5924 } | 5907 } |
| 5925 } | 5908 } |
| 5926 __ Bind(&is_ok); | 5909 __ Bind(&is_ok); |
| 5927 } | 5910 } |
| 5928 | 5911 |
| 5929 | 5912 |
| 5930 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5913 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
| 5931 bool opt) const { | 5914 bool opt) const { |
| 5932 const intptr_t kNumInputs = 1; | 5915 const intptr_t kNumInputs = 1; |
| 5933 const intptr_t kNumTemps = 0; | 5916 const intptr_t kNumTemps = 0; |
| 5934 LocationSummary* summary = new(zone) LocationSummary( | 5917 LocationSummary* summary = new (zone) |
| 5935 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5918 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5936 summary->set_in(0, Location::RequiresRegister()); | 5919 summary->set_in(0, Location::RequiresRegister()); |
| 5937 return summary; | 5920 return summary; |
| 5938 } | 5921 } |
| 5939 | 5922 |
| 5940 | 5923 |
| 5941 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5924 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5942 Register value = locs()->in(0).reg(); | 5925 Register value = locs()->in(0).reg(); |
| 5943 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5926 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
| 5944 ICData::kDeoptCheckSmi, | |
| 5945 licm_hoisted_ ? ICData::kHoisted : 0); | 5927 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5946 __ BranchIfNotSmi(value, deopt); | 5928 __ BranchIfNotSmi(value, deopt); |
| 5947 } | 5929 } |
| 5948 | 5930 |
| 5949 | 5931 |
| 5950 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5932 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
| 5951 bool opt) const { | 5933 bool opt) const { |
| 5952 const intptr_t kNumInputs = 1; | 5934 const intptr_t kNumInputs = 1; |
| 5953 const intptr_t kNumTemps = 0; | 5935 const intptr_t kNumTemps = 0; |
| 5954 LocationSummary* summary = new(zone) LocationSummary( | 5936 LocationSummary* summary = new (zone) |
| 5955 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5937 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5956 summary->set_in(0, Location::RequiresRegister()); | 5938 summary->set_in(0, Location::RequiresRegister()); |
| 5957 return summary; | 5939 return summary; |
| 5958 } | 5940 } |
| 5959 | 5941 |
| 5960 | 5942 |
| 5961 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5943 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5962 Register value = locs()->in(0).reg(); | 5944 Register value = locs()->in(0).reg(); |
| 5963 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5945 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
| 5964 __ cmpl(value, Immediate(Smi::RawValue(cid_))); | 5946 __ cmpl(value, Immediate(Smi::RawValue(cid_))); |
| 5965 __ j(NOT_ZERO, deopt); | 5947 __ j(NOT_ZERO, deopt); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5979 UNIMPLEMENTED(); | 5961 UNIMPLEMENTED(); |
| 5980 } | 5962 } |
| 5981 | 5963 |
| 5982 | 5964 |
| 5983 // Length: register or constant. | 5965 // Length: register or constant. |
| 5984 // Index: register, constant or stack slot. | 5966 // Index: register, constant or stack slot. |
| 5985 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5967 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
| 5986 bool opt) const { | 5968 bool opt) const { |
| 5987 const intptr_t kNumInputs = 2; | 5969 const intptr_t kNumInputs = 2; |
| 5988 const intptr_t kNumTemps = 0; | 5970 const intptr_t kNumTemps = 0; |
| 5989 LocationSummary* locs = new(zone) LocationSummary( | 5971 LocationSummary* locs = new (zone) |
| 5990 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5972 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5991 if (length()->definition()->IsConstant()) { | 5973 if (length()->definition()->IsConstant()) { |
| 5992 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5974 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
| 5993 } else { | 5975 } else { |
| 5994 locs->set_in(kLengthPos, Location::PrefersRegister()); | 5976 locs->set_in(kLengthPos, Location::PrefersRegister()); |
| 5995 } | 5977 } |
| 5996 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5978 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
| 5997 return locs; | 5979 return locs; |
| 5998 } | 5980 } |
| 5999 | 5981 |
| 6000 | 5982 |
| 6001 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5983 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6002 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5984 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
| 6003 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5985 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
| 6004 Label* deopt = compiler->AddDeoptStub( | 5986 Label* deopt = |
| 6005 deopt_id(), | 5987 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
| 6006 ICData::kDeoptCheckArrayBound, | |
| 6007 flags); | |
| 6008 | 5988 |
| 6009 Location length_loc = locs()->in(kLengthPos); | 5989 Location length_loc = locs()->in(kLengthPos); |
| 6010 Location index_loc = locs()->in(kIndexPos); | 5990 Location index_loc = locs()->in(kIndexPos); |
| 6011 | 5991 |
| 6012 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5992 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
| 6013 ASSERT((Smi::Cast(length_loc.constant()).Value() <= | 5993 ASSERT((Smi::Cast(length_loc.constant()).Value() <= |
| 6014 Smi::Cast(index_loc.constant()).Value()) || | 5994 Smi::Cast(index_loc.constant()).Value()) || |
| 6015 (Smi::Cast(index_loc.constant()).Value() < 0)); | 5995 (Smi::Cast(index_loc.constant()).Value() < 0)); |
| 6016 // Unconditionally deoptimize for constant bounds checks because they | 5996 // Unconditionally deoptimize for constant bounds checks because they |
| 6017 // only occur only when index is out-of-bounds. | 5997 // only occur only when index is out-of-bounds. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6067 bool opt) const { | 6047 bool opt) const { |
| 6068 const intptr_t kNumInputs = 2; | 6048 const intptr_t kNumInputs = 2; |
| 6069 switch (op_kind()) { | 6049 switch (op_kind()) { |
| 6070 case Token::kBIT_AND: | 6050 case Token::kBIT_AND: |
| 6071 case Token::kBIT_OR: | 6051 case Token::kBIT_OR: |
| 6072 case Token::kBIT_XOR: | 6052 case Token::kBIT_XOR: |
| 6073 case Token::kADD: | 6053 case Token::kADD: |
| 6074 case Token::kSUB: | 6054 case Token::kSUB: |
| 6075 case Token::kMUL: { | 6055 case Token::kMUL: { |
| 6076 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; | 6056 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
| 6077 LocationSummary* summary = new(zone) LocationSummary( | 6057 LocationSummary* summary = new (zone) LocationSummary( |
| 6078 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6058 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6079 summary->set_in(0, (op_kind() == Token::kMUL) | 6059 summary->set_in(0, (op_kind() == Token::kMUL) |
| 6080 ? Location::Pair(Location::RegisterLocation(EAX), | 6060 ? Location::Pair(Location::RegisterLocation(EAX), |
| 6081 Location::RegisterLocation(EDX)) | 6061 Location::RegisterLocation(EDX)) |
| 6082 : Location::Pair(Location::RequiresRegister(), | 6062 : Location::Pair(Location::RequiresRegister(), |
| 6083 Location::RequiresRegister())); | 6063 Location::RequiresRegister())); |
| 6084 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | 6064 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 6085 Location::RequiresRegister())); | 6065 Location::RequiresRegister())); |
| 6086 summary->set_out(0, Location::SameAsFirstInput()); | 6066 summary->set_out(0, Location::SameAsFirstInput()); |
| 6087 if (kNumTemps > 0) { | 6067 if (kNumTemps > 0) { |
| 6088 summary->set_temp(0, Location::RequiresRegister()); | 6068 summary->set_temp(0, Location::RequiresRegister()); |
| 6089 } | 6069 } |
| 6090 return summary; | 6070 return summary; |
| 6091 } | 6071 } |
| 6092 default: | 6072 default: |
| 6093 UNREACHABLE(); | 6073 UNREACHABLE(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6164 UNREACHABLE(); | 6144 UNREACHABLE(); |
| 6165 } | 6145 } |
| 6166 } | 6146 } |
| 6167 | 6147 |
| 6168 | 6148 |
| 6169 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 6149 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6170 bool opt) const { | 6150 bool opt) const { |
| 6171 const intptr_t kNumInputs = 2; | 6151 const intptr_t kNumInputs = 2; |
| 6172 const intptr_t kNumTemps = | 6152 const intptr_t kNumTemps = |
| 6173 (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0; | 6153 (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0; |
| 6174 LocationSummary* summary = new(zone) LocationSummary( | 6154 LocationSummary* summary = new (zone) |
| 6175 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6155 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6176 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6156 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6177 Location::RequiresRegister())); | 6157 Location::RequiresRegister())); |
| 6178 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 6158 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 6179 if ((op_kind() == Token::kSHL) && CanDeoptimize()) { | 6159 if ((op_kind() == Token::kSHL) && CanDeoptimize()) { |
| 6180 summary->set_temp(0, Location::RequiresRegister()); | 6160 summary->set_temp(0, Location::RequiresRegister()); |
| 6181 summary->set_temp(1, Location::RequiresRegister()); | 6161 summary->set_temp(1, Location::RequiresRegister()); |
| 6182 } | 6162 } |
| 6183 summary->set_out(0, Location::SameAsFirstInput()); | 6163 summary->set_out(0, Location::SameAsFirstInput()); |
| 6184 return summary; | 6164 return summary; |
| 6185 } | 6165 } |
| 6186 | 6166 |
| 6187 | 6167 |
| 6188 static const intptr_t kMintShiftCountLimit = 63; | 6168 static const intptr_t kMintShiftCountLimit = 63; |
| 6189 | 6169 |
| 6190 bool ShiftMintOpInstr::has_shift_count_check() const { | 6170 bool ShiftMintOpInstr::has_shift_count_check() const { |
| 6191 return !RangeUtils::IsWithin( | 6171 return !RangeUtils::IsWithin(right()->definition()->range(), 0, |
| 6192 right()->definition()->range(), 0, kMintShiftCountLimit); | 6172 kMintShiftCountLimit); |
| 6193 } | 6173 } |
| 6194 | 6174 |
| 6195 | 6175 |
| 6196 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6176 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6197 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6177 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 6198 Register left_lo = left_pair->At(0).reg(); | 6178 Register left_lo = left_pair->At(0).reg(); |
| 6199 Register left_hi = left_pair->At(1).reg(); | 6179 Register left_hi = left_pair->At(1).reg(); |
| 6200 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6180 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 6201 Register out_lo = out_pair->At(0).reg(); | 6181 Register out_lo = out_pair->At(0).reg(); |
| 6202 Register out_hi = out_pair->At(1).reg(); | 6182 Register out_hi = out_pair->At(1).reg(); |
| 6203 ASSERT(out_lo == left_lo); | 6183 ASSERT(out_lo == left_lo); |
| 6204 ASSERT(out_hi == left_hi); | 6184 ASSERT(out_hi == left_hi); |
| 6205 | 6185 |
| 6206 Label* deopt = NULL; | 6186 Label* deopt = NULL; |
| 6207 if (CanDeoptimize()) { | 6187 if (CanDeoptimize()) { |
| 6208 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6188 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 6209 } | 6189 } |
| 6210 if (locs()->in(1).IsConstant()) { | 6190 if (locs()->in(1).IsConstant()) { |
| 6211 // Code for a constant shift amount. | 6191 // Code for a constant shift amount. |
| 6212 ASSERT(locs()->in(1).constant().IsSmi()); | 6192 ASSERT(locs()->in(1).constant().IsSmi()); |
| 6213 const int32_t shift = | 6193 const int32_t shift = |
| 6214 reinterpret_cast<int32_t>(locs()->in(1).constant().raw()) >> 1; | 6194 reinterpret_cast<int32_t>(locs()->in(1).constant().raw()) >> 1; |
| 6215 switch (op_kind()) { | 6195 switch (op_kind()) { |
| 6216 case Token::kSHR: { | 6196 case Token::kSHR: { |
| 6217 if (shift > 31) { | 6197 if (shift > 31) { |
| 6218 __ movl(left_lo, left_hi); // Shift by 32. | 6198 __ movl(left_lo, left_hi); // Shift by 32. |
| 6219 __ sarl(left_hi, Immediate(31)); // Sign extend left hi. | 6199 __ sarl(left_hi, Immediate(31)); // Sign extend left hi. |
| 6220 if (shift > 32) { | 6200 if (shift > 32) { |
| 6221 __ sarl(left_lo, Immediate(shift > 63 ? 31 : shift - 32)); | 6201 __ sarl(left_lo, Immediate(shift > 63 ? 31 : shift - 32)); |
| 6222 } | 6202 } |
| 6223 } else { | 6203 } else { |
| 6224 __ shrdl(left_lo, left_hi, Immediate(shift)); | 6204 __ shrdl(left_lo, left_hi, Immediate(shift)); |
| 6225 __ sarl(left_hi, Immediate(shift)); | 6205 __ sarl(left_hi, Immediate(shift)); |
| 6226 } | 6206 } |
| 6227 break; | 6207 break; |
| 6228 } | 6208 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6289 __ cmpl(ECX, Immediate(kMintShiftCountLimit)); | 6269 __ cmpl(ECX, Immediate(kMintShiftCountLimit)); |
| 6290 __ j(ABOVE, deopt); | 6270 __ j(ABOVE, deopt); |
| 6291 } | 6271 } |
| 6292 Label done, large_shift; | 6272 Label done, large_shift; |
| 6293 switch (op_kind()) { | 6273 switch (op_kind()) { |
| 6294 case Token::kSHR: { | 6274 case Token::kSHR: { |
| 6295 __ cmpl(ECX, Immediate(31)); | 6275 __ cmpl(ECX, Immediate(31)); |
| 6296 __ j(ABOVE, &large_shift); | 6276 __ j(ABOVE, &large_shift); |
| 6297 | 6277 |
| 6298 __ shrdl(left_lo, left_hi, ECX); // Shift count in CL. | 6278 __ shrdl(left_lo, left_hi, ECX); // Shift count in CL. |
| 6299 __ sarl(left_hi, ECX); // Shift count in CL. | 6279 __ sarl(left_hi, ECX); // Shift count in CL. |
| 6300 __ jmp(&done, Assembler::kNearJump); | 6280 __ jmp(&done, Assembler::kNearJump); |
| 6301 | 6281 |
| 6302 __ Bind(&large_shift); | 6282 __ Bind(&large_shift); |
| 6303 // No need to subtract 32 from CL, only 5 bits used by sarl. | 6283 // No need to subtract 32 from CL, only 5 bits used by sarl. |
| 6304 __ movl(left_lo, left_hi); // Shift by 32. | 6284 __ movl(left_lo, left_hi); // Shift by 32. |
| 6305 __ sarl(left_hi, Immediate(31)); // Sign extend left hi. | 6285 __ sarl(left_hi, Immediate(31)); // Sign extend left hi. |
| 6306 __ sarl(left_lo, ECX); // Shift count: CL % 32. | 6286 __ sarl(left_lo, ECX); // Shift count: CL % 32. |
| 6307 break; | 6287 break; |
| 6308 } | 6288 } |
| 6309 case Token::kSHL: { | 6289 case Token::kSHL: { |
| 6310 if (can_overflow()) { | 6290 if (can_overflow()) { |
| 6311 Register temp1 = locs()->temp(0).reg(); | 6291 Register temp1 = locs()->temp(0).reg(); |
| 6312 Register temp2 = locs()->temp(1).reg(); | 6292 Register temp2 = locs()->temp(1).reg(); |
| 6313 __ movl(temp1, left_hi); // Preserve high 32 bits. | 6293 __ movl(temp1, left_hi); // Preserve high 32 bits. |
| 6314 __ cmpl(ECX, Immediate(31)); | 6294 __ cmpl(ECX, Immediate(31)); |
| 6315 __ j(ABOVE, &large_shift); | 6295 __ j(ABOVE, &large_shift); |
| 6316 | 6296 |
| 6317 __ shldl(left_hi, left_lo, ECX); // Shift count in CL. | 6297 __ shldl(left_hi, left_lo, ECX); // Shift count in CL. |
| 6318 __ shll(left_lo, ECX); // Shift count in CL. | 6298 __ shll(left_lo, ECX); // Shift count in CL. |
| 6319 // Check for overflow by shifting back the high 32 bits | 6299 // Check for overflow by shifting back the high 32 bits |
| 6320 // and comparing with the input. | 6300 // and comparing with the input. |
| 6321 __ movl(temp2, left_hi); | 6301 __ movl(temp2, left_hi); |
| 6322 __ sarl(temp2, ECX); | 6302 __ sarl(temp2, ECX); |
| 6323 __ cmpl(temp1, temp2); | 6303 __ cmpl(temp1, temp2); |
| 6324 __ j(NOT_EQUAL, deopt); | 6304 __ j(NOT_EQUAL, deopt); |
| 6325 __ jmp(&done, Assembler::kNearJump); | 6305 __ jmp(&done, Assembler::kNearJump); |
| 6326 | 6306 |
| 6327 __ Bind(&large_shift); | 6307 __ Bind(&large_shift); |
| 6328 // No need to subtract 32 from CL, only 5 bits used by shll. | 6308 // No need to subtract 32 from CL, only 5 bits used by shll. |
| 6329 __ movl(left_hi, left_lo); // Shift by 32. | 6309 __ movl(left_hi, left_lo); // Shift by 32. |
| 6330 __ shll(left_hi, ECX); // Shift count: CL % 32. | 6310 __ shll(left_hi, ECX); // Shift count: CL % 32. |
| 6331 // Check for overflow by sign extending the high 32 bits | 6311 // Check for overflow by sign extending the high 32 bits |
| 6332 // and comparing with the input. | 6312 // and comparing with the input. |
| 6333 __ movl(temp2, left_hi); | 6313 __ movl(temp2, left_hi); |
| 6334 __ sarl(temp2, Immediate(31)); | 6314 __ sarl(temp2, Immediate(31)); |
| 6335 __ cmpl(temp1, temp2); | 6315 __ cmpl(temp1, temp2); |
| 6336 __ j(NOT_EQUAL, deopt); | 6316 __ j(NOT_EQUAL, deopt); |
| 6337 // Also compare low word from input with high word from | 6317 // Also compare low word from input with high word from |
| 6338 // output shifted back shift - 32. | 6318 // output shifted back shift - 32. |
| 6339 __ movl(temp2, left_hi); | 6319 __ movl(temp2, left_hi); |
| 6340 __ sarl(temp2, ECX); // Shift count: CL % 32. | 6320 __ sarl(temp2, ECX); // Shift count: CL % 32. |
| 6341 __ cmpl(left_lo, temp2); | 6321 __ cmpl(left_lo, temp2); |
| 6342 __ j(NOT_EQUAL, deopt); | 6322 __ j(NOT_EQUAL, deopt); |
| 6343 __ xorl(left_lo, left_lo); // Zero left_lo. | 6323 __ xorl(left_lo, left_lo); // Zero left_lo. |
| 6344 } else { | 6324 } else { |
| 6345 __ cmpl(ECX, Immediate(31)); | 6325 __ cmpl(ECX, Immediate(31)); |
| 6346 __ j(ABOVE, &large_shift); | 6326 __ j(ABOVE, &large_shift); |
| 6347 | 6327 |
| 6348 __ shldl(left_hi, left_lo, ECX); // Shift count in CL. | 6328 __ shldl(left_hi, left_lo, ECX); // Shift count in CL. |
| 6349 __ shll(left_lo, ECX); // Shift count in CL. | 6329 __ shll(left_lo, ECX); // Shift count in CL. |
| 6350 __ jmp(&done, Assembler::kNearJump); | 6330 __ jmp(&done, Assembler::kNearJump); |
| 6351 | 6331 |
| 6352 __ Bind(&large_shift); | 6332 __ Bind(&large_shift); |
| 6353 // No need to subtract 32 from CL, only 5 bits used by shll. | 6333 // No need to subtract 32 from CL, only 5 bits used by shll. |
| 6354 __ movl(left_hi, left_lo); // Shift by 32. | 6334 __ movl(left_hi, left_lo); // Shift by 32. |
| 6355 __ xorl(left_lo, left_lo); // Zero left_lo. | 6335 __ xorl(left_lo, left_lo); // Zero left_lo. |
| 6356 __ shll(left_hi, ECX); // Shift count: CL % 32. | 6336 __ shll(left_hi, ECX); // Shift count: CL % 32. |
| 6357 } | 6337 } |
| 6358 break; | 6338 break; |
| 6359 } | 6339 } |
| 6360 default: | 6340 default: |
| 6361 UNREACHABLE(); | 6341 UNREACHABLE(); |
| 6362 } | 6342 } |
| 6363 __ Bind(&done); | 6343 __ Bind(&done); |
| 6364 } | 6344 } |
| 6365 } | 6345 } |
| 6366 | 6346 |
| 6367 | 6347 |
| 6368 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 6348 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6369 bool opt) const { | 6349 bool opt) const { |
| 6370 const intptr_t kNumInputs = 1; | 6350 const intptr_t kNumInputs = 1; |
| 6371 const intptr_t kNumTemps = 0; | 6351 const intptr_t kNumTemps = 0; |
| 6372 LocationSummary* summary = new(zone) LocationSummary( | 6352 LocationSummary* summary = new (zone) |
| 6373 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6353 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6374 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6354 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6375 Location::RequiresRegister())); | 6355 Location::RequiresRegister())); |
| 6376 summary->set_out(0, Location::SameAsFirstInput()); | 6356 summary->set_out(0, Location::SameAsFirstInput()); |
| 6377 return summary; | 6357 return summary; |
| 6378 } | 6358 } |
| 6379 | 6359 |
| 6380 | 6360 |
| 6381 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6361 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6382 ASSERT(op_kind() == Token::kBIT_NOT); | 6362 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6383 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6363 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 6405 | 6385 |
| 6406 CompileType UnaryUint32OpInstr::ComputeType() const { | 6386 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 6407 return CompileType::Int(); | 6387 return CompileType::Int(); |
| 6408 } | 6388 } |
| 6409 | 6389 |
| 6410 | 6390 |
| 6411 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 6391 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6412 bool opt) const { | 6392 bool opt) const { |
| 6413 const intptr_t kNumInputs = 2; | 6393 const intptr_t kNumInputs = 2; |
| 6414 const intptr_t kNumTemps = 0; | 6394 const intptr_t kNumTemps = 0; |
| 6415 LocationSummary* summary = new(zone) LocationSummary( | 6395 LocationSummary* summary = new (zone) |
| 6416 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6396 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6417 summary->set_in(0, Location::RequiresRegister()); | 6397 summary->set_in(0, Location::RequiresRegister()); |
| 6418 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 6398 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 6419 summary->set_out(0, Location::SameAsFirstInput()); | 6399 summary->set_out(0, Location::SameAsFirstInput()); |
| 6420 return summary; | 6400 return summary; |
| 6421 } | 6401 } |
| 6422 | 6402 |
| 6423 | 6403 |
| 6424 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6404 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6425 const intptr_t kShifterLimit = 31; | 6405 const intptr_t kShifterLimit = 31; |
| 6426 | 6406 |
| 6427 Register left = locs()->in(0).reg(); | 6407 Register left = locs()->in(0).reg(); |
| 6428 Register out = locs()->out(0).reg(); | 6408 Register out = locs()->out(0).reg(); |
| 6429 ASSERT(left == out); | 6409 ASSERT(left == out); |
| 6430 | 6410 |
| 6431 | 6411 |
| 6432 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6412 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 6433 | 6413 |
| 6434 if (locs()->in(1).IsConstant()) { | 6414 if (locs()->in(1).IsConstant()) { |
| 6435 // Shifter is constant. | 6415 // Shifter is constant. |
| 6436 | 6416 |
| 6437 const Object& constant = locs()->in(1).constant(); | 6417 const Object& constant = locs()->in(1).constant(); |
| 6438 ASSERT(constant.IsSmi()); | 6418 ASSERT(constant.IsSmi()); |
| 6439 const intptr_t shift_value = Smi::Cast(constant).Value(); | 6419 const intptr_t shift_value = Smi::Cast(constant).Value(); |
| 6440 | 6420 |
| 6441 | 6421 |
| 6442 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | 6422 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
| 6443 switch (op_kind()) { | 6423 switch (op_kind()) { |
| 6444 case Token::kSHR: | 6424 case Token::kSHR: |
| 6445 __ shrl(left, Immediate(shift_value)); | 6425 __ shrl(left, Immediate(shift_value)); |
| 6446 break; | 6426 break; |
| 6447 case Token::kSHL: | 6427 case Token::kSHL: |
| 6448 __ shll(left, Immediate(shift_value)); | 6428 __ shll(left, Immediate(shift_value)); |
| 6449 break; | 6429 break; |
| 6450 default: | 6430 default: |
| 6451 UNREACHABLE(); | 6431 UNREACHABLE(); |
| 6452 } | 6432 } |
| 6453 return; | 6433 return; |
| 6454 } | 6434 } |
| 6455 | 6435 |
| 6456 // Non constant shift value. | 6436 // Non constant shift value. |
| 6457 | 6437 |
| 6458 Register shifter = locs()->in(1).reg(); | 6438 Register shifter = locs()->in(1).reg(); |
| 6459 ASSERT(shifter == ECX); | 6439 ASSERT(shifter == ECX); |
| 6460 | 6440 |
| 6461 Label done; | 6441 Label done; |
| 6462 Label zero; | 6442 Label zero; |
| 6463 | 6443 |
| 6464 // TODO(johnmccutchan): Use range information to avoid these checks. | 6444 // TODO(johnmccutchan): Use range information to avoid these checks. |
| 6465 __ SmiUntag(shifter); | 6445 __ SmiUntag(shifter); |
| 6466 __ cmpl(shifter, Immediate(0)); | 6446 __ cmpl(shifter, Immediate(0)); |
| 6467 // If shift value is < 0, deoptimize. | 6447 // If shift value is < 0, deoptimize. |
| 6468 __ j(NEGATIVE, deopt); | 6448 __ j(NEGATIVE, deopt); |
| 6469 __ cmpl(shifter, Immediate(kShifterLimit)); | 6449 __ cmpl(shifter, Immediate(kShifterLimit)); |
| 6470 // If shift value is >= 32, return zero. | 6450 // If shift value is >= 32, return zero. |
| 6471 __ j(ABOVE, &zero); | 6451 __ j(ABOVE, &zero); |
| 6472 | 6452 |
| 6473 // Do the shift. | 6453 // Do the shift. |
| 6474 switch (op_kind()) { | 6454 switch (op_kind()) { |
| 6475 case Token::kSHR: | 6455 case Token::kSHR: |
| 6476 __ shrl(left, shifter); | 6456 __ shrl(left, shifter); |
| 6477 __ jmp(&done); | 6457 __ jmp(&done); |
| 6478 break; | 6458 break; |
| 6479 case Token::kSHL: | 6459 case Token::kSHL: |
| 6480 __ shll(left, shifter); | 6460 __ shll(left, shifter); |
| 6481 __ jmp(&done); | 6461 __ jmp(&done); |
| 6482 break; | 6462 break; |
| 6483 default: | 6463 default: |
| 6484 UNREACHABLE(); | 6464 UNREACHABLE(); |
| 6485 } | 6465 } |
| 6486 | 6466 |
| 6487 __ Bind(&zero); | 6467 __ Bind(&zero); |
| 6488 // Shift was greater than 31 bits, just return zero. | 6468 // Shift was greater than 31 bits, just return zero. |
| 6489 __ xorl(left, left); | 6469 __ xorl(left, left); |
| 6490 | 6470 |
| 6491 // Exit path. | 6471 // Exit path. |
| 6492 __ Bind(&done); | 6472 __ Bind(&done); |
| 6493 } | 6473 } |
| 6494 | 6474 |
| 6495 | 6475 |
| 6496 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6476 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6497 bool opt) const { | 6477 bool opt) const { |
| 6498 const intptr_t kNumInputs = 1; | 6478 const intptr_t kNumInputs = 1; |
| 6499 const intptr_t kNumTemps = 0; | 6479 const intptr_t kNumTemps = 0; |
| 6500 LocationSummary* summary = new(zone) LocationSummary( | 6480 LocationSummary* summary = new (zone) |
| 6501 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6481 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6502 summary->set_in(0, Location::RequiresRegister()); | 6482 summary->set_in(0, Location::RequiresRegister()); |
| 6503 summary->set_out(0, Location::SameAsFirstInput()); | 6483 summary->set_out(0, Location::SameAsFirstInput()); |
| 6504 return summary; | 6484 return summary; |
| 6505 } | 6485 } |
| 6506 | 6486 |
| 6507 | 6487 |
| 6508 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6488 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6509 Register out = locs()->out(0).reg(); | 6489 Register out = locs()->out(0).reg(); |
| 6510 ASSERT(locs()->in(0).reg() == out); | 6490 ASSERT(locs()->in(0).reg() == out); |
| 6511 | 6491 |
| 6512 ASSERT(op_kind() == Token::kBIT_NOT); | 6492 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6513 | 6493 |
| 6514 __ notl(out); | 6494 __ notl(out); |
| 6515 } | 6495 } |
| 6516 | 6496 |
| 6517 | 6497 |
| 6518 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 6498 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
| 6519 bool opt) const { | 6499 bool opt) const { |
| 6520 const intptr_t kNumInputs = 1; | 6500 const intptr_t kNumInputs = 1; |
| 6521 const intptr_t kNumTemps = 0; | 6501 const intptr_t kNumTemps = 0; |
| 6522 LocationSummary* summary = new(zone) LocationSummary( | 6502 LocationSummary* summary = new (zone) |
| 6523 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6503 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6524 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) && | 6504 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) && |
| 6525 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) { | 6505 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) { |
| 6526 summary->set_in(0, Location::RequiresRegister()); | 6506 summary->set_in(0, Location::RequiresRegister()); |
| 6527 summary->set_out(0, Location::SameAsFirstInput()); | 6507 summary->set_out(0, Location::SameAsFirstInput()); |
| 6528 } else if (from() == kUnboxedMint) { | 6508 } else if (from() == kUnboxedMint) { |
| 6529 summary->set_in(0, Location::Pair( | 6509 summary->set_in( |
| 6530 CanDeoptimize() ? Location::WritableRegister() | 6510 0, Location::Pair(CanDeoptimize() ? Location::WritableRegister() |
| 6531 : Location::RequiresRegister(), | 6511 : Location::RequiresRegister(), |
| 6532 Location::RequiresRegister())); | 6512 Location::RequiresRegister())); |
| 6533 summary->set_out(0, Location::RequiresRegister()); | 6513 summary->set_out(0, Location::RequiresRegister()); |
| 6534 } else if (from() == kUnboxedUint32) { | 6514 } else if (from() == kUnboxedUint32) { |
| 6535 summary->set_in(0, Location::RequiresRegister()); | 6515 summary->set_in(0, Location::RequiresRegister()); |
| 6536 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6516 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 6537 Location::RequiresRegister())); | 6517 Location::RequiresRegister())); |
| 6538 } else if (from() == kUnboxedInt32) { | 6518 } else if (from() == kUnboxedInt32) { |
| 6539 summary->set_in(0, Location::RegisterLocation(EAX)); | 6519 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 6540 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 6520 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
| 6541 Location::RegisterLocation(EDX))); | 6521 Location::RegisterLocation(EDX))); |
| 6542 } | 6522 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6593 Register out_hi = out_pair->At(1).reg(); | 6573 Register out_hi = out_pair->At(1).reg(); |
| 6594 ASSERT(locs()->in(0).reg() == EAX); | 6574 ASSERT(locs()->in(0).reg() == EAX); |
| 6595 ASSERT(out_lo == EAX && out_hi == EDX); | 6575 ASSERT(out_lo == EAX && out_hi == EDX); |
| 6596 __ cdq(); | 6576 __ cdq(); |
| 6597 } else { | 6577 } else { |
| 6598 UNREACHABLE(); | 6578 UNREACHABLE(); |
| 6599 } | 6579 } |
| 6600 } | 6580 } |
| 6601 | 6581 |
| 6602 | 6582 |
| 6603 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, | 6583 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6604 bool opt) const { | 6584 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 6605 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
| 6606 } | 6585 } |
| 6607 | 6586 |
| 6608 | 6587 |
| 6609 | |
| 6610 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6588 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6611 compiler->GenerateRuntimeCall(token_pos(), | 6589 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
| 6612 deopt_id(), | |
| 6613 kThrowRuntimeEntry, | |
| 6614 1, | |
| 6615 locs()); | 6590 locs()); |
| 6616 __ int3(); | 6591 __ int3(); |
| 6617 } | 6592 } |
| 6618 | 6593 |
| 6619 | 6594 |
| 6620 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, | 6595 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6621 bool opt) const { | 6596 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 6622 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
| 6623 } | 6597 } |
| 6624 | 6598 |
| 6625 | 6599 |
| 6626 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6600 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6627 compiler->SetNeedsStacktrace(catch_try_index()); | 6601 compiler->SetNeedsStacktrace(catch_try_index()); |
| 6628 compiler->GenerateRuntimeCall(token_pos(), | 6602 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
| 6629 deopt_id(), | 6603 2, locs()); |
| 6630 kReThrowRuntimeEntry, | |
| 6631 2, | |
| 6632 locs()); | |
| 6633 __ int3(); | 6604 __ int3(); |
| 6634 } | 6605 } |
| 6635 | 6606 |
| 6636 | 6607 |
| 6637 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, | 6608 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6638 bool opt) const { | 6609 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 6639 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
| 6640 } | 6610 } |
| 6641 | 6611 |
| 6642 | 6612 |
| 6643 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6613 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6644 __ Stop(message()); | 6614 __ Stop(message()); |
| 6645 } | 6615 } |
| 6646 | 6616 |
| 6647 | 6617 |
| 6648 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6618 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6649 if (!compiler->CanFallThroughTo(normal_entry())) { | 6619 if (!compiler->CanFallThroughTo(normal_entry())) { |
| 6650 __ jmp(compiler->GetJumpLabel(normal_entry())); | 6620 __ jmp(compiler->GetJumpLabel(normal_entry())); |
| 6651 } | 6621 } |
| 6652 } | 6622 } |
| 6653 | 6623 |
| 6654 | 6624 |
| 6655 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, | 6625 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6656 bool opt) const { | 6626 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 6657 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
| 6658 } | 6627 } |
| 6659 | 6628 |
| 6660 | 6629 |
| 6661 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6630 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6662 if (!compiler->is_optimizing()) { | 6631 if (!compiler->is_optimizing()) { |
| 6663 if (FLAG_reorder_basic_blocks) { | 6632 if (FLAG_reorder_basic_blocks) { |
| 6664 compiler->EmitEdgeCounter(block()->preorder_number()); | 6633 compiler->EmitEdgeCounter(block()->preorder_number()); |
| 6665 } | 6634 } |
| 6666 // Add a deoptimization descriptor for deoptimizing instructions that | 6635 // Add a deoptimization descriptor for deoptimizing instructions that |
| 6667 // may be inserted before this instruction. | 6636 // may be inserted before this instruction. |
| 6668 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 6637 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
| 6669 GetDeoptId(), | |
| 6670 TokenPosition::kNoSource); | 6638 TokenPosition::kNoSource); |
| 6671 } | 6639 } |
| 6672 if (HasParallelMove()) { | 6640 if (HasParallelMove()) { |
| 6673 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 6641 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 6674 } | 6642 } |
| 6675 | 6643 |
| 6676 // We can fall through if the successor is the next block in the list. | 6644 // We can fall through if the successor is the next block in the list. |
| 6677 // Otherwise, we need a jump. | 6645 // Otherwise, we need a jump. |
| 6678 if (!compiler->CanFallThroughTo(successor())) { | 6646 if (!compiler->CanFallThroughTo(successor())) { |
| 6679 __ jmp(compiler->GetJumpLabel(successor())); | 6647 __ jmp(compiler->GetJumpLabel(successor())); |
| 6680 } | 6648 } |
| 6681 } | 6649 } |
| 6682 | 6650 |
| 6683 | 6651 |
| 6684 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 6652 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
| 6685 bool opt) const { | 6653 bool opt) const { |
| 6686 const intptr_t kNumInputs = 1; | 6654 const intptr_t kNumInputs = 1; |
| 6687 const intptr_t kNumTemps = 1; | 6655 const intptr_t kNumTemps = 1; |
| 6688 | 6656 |
| 6689 LocationSummary* summary = new(zone) LocationSummary( | 6657 LocationSummary* summary = new (zone) |
| 6690 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6658 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6691 | 6659 |
| 6692 summary->set_in(0, Location::RequiresRegister()); | 6660 summary->set_in(0, Location::RequiresRegister()); |
| 6693 summary->set_temp(0, Location::RequiresRegister()); | 6661 summary->set_temp(0, Location::RequiresRegister()); |
| 6694 | 6662 |
| 6695 return summary; | 6663 return summary; |
| 6696 } | 6664 } |
| 6697 | 6665 |
| 6698 | 6666 |
| 6699 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6667 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6700 Register target_reg = locs()->temp_slot(0)->reg(); | 6668 Register target_reg = locs()->temp_slot(0)->reg(); |
| 6701 | 6669 |
| 6702 // Load code object from frame. | 6670 // Load code object from frame. |
| 6703 __ movl(target_reg, Address(EBP, kPcMarkerSlotFromFp * kWordSize)); | 6671 __ movl(target_reg, Address(EBP, kPcMarkerSlotFromFp * kWordSize)); |
| 6704 // Load instructions object (active_instructions and Code::entry_point() may | 6672 // Load instructions object (active_instructions and Code::entry_point() may |
| 6705 // not point to this instruction object any more; see Code::DisableDartCode). | 6673 // not point to this instruction object any more; see Code::DisableDartCode). |
| 6706 __ movl(target_reg, | 6674 __ movl(target_reg, |
| 6707 FieldAddress(target_reg, Code::saved_instructions_offset())); | 6675 FieldAddress(target_reg, Code::saved_instructions_offset())); |
| 6708 __ addl(target_reg, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 6676 __ addl(target_reg, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 6709 | 6677 |
| 6710 // Add the offset. | 6678 // Add the offset. |
| 6711 Register offset_reg = locs()->in(0).reg(); | 6679 Register offset_reg = locs()->in(0).reg(); |
| 6712 if (offset()->definition()->representation() == kTagged) { | 6680 if (offset()->definition()->representation() == kTagged) { |
| 6713 __ SmiUntag(offset_reg); | 6681 __ SmiUntag(offset_reg); |
| 6714 } | 6682 } |
| 6715 __ addl(target_reg, offset_reg); | 6683 __ addl(target_reg, offset_reg); |
| 6716 | 6684 |
| 6717 // Jump to the absolute address. | 6685 // Jump to the absolute address. |
| 6718 __ jmp(target_reg); | 6686 __ jmp(target_reg); |
| 6719 } | 6687 } |
| 6720 | 6688 |
| 6721 | 6689 |
| 6722 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 6690 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
| 6723 bool opt) const { | 6691 bool opt) const { |
| 6724 const intptr_t kNumInputs = 2; | 6692 const intptr_t kNumInputs = 2; |
| 6725 const intptr_t kNumTemps = 0; | 6693 const intptr_t kNumTemps = 0; |
| 6726 if (needs_number_check()) { | 6694 if (needs_number_check()) { |
| 6727 LocationSummary* locs = new(zone) LocationSummary( | 6695 LocationSummary* locs = new (zone) |
| 6728 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6696 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6729 locs->set_in(0, Location::RegisterLocation(EAX)); | 6697 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 6730 locs->set_in(1, Location::RegisterLocation(ECX)); | 6698 locs->set_in(1, Location::RegisterLocation(ECX)); |
| 6731 locs->set_out(0, Location::RegisterLocation(EAX)); | 6699 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 6732 return locs; | 6700 return locs; |
| 6733 } | 6701 } |
| 6734 LocationSummary* locs = new(zone) LocationSummary( | 6702 LocationSummary* locs = new (zone) |
| 6735 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6703 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6736 locs->set_in(0, Location::RegisterOrConstant(left())); | 6704 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 6737 // Only one of the inputs can be a constant. Choose register if the first one | 6705 // Only one of the inputs can be a constant. Choose register if the first one |
| 6738 // is a constant. | 6706 // is a constant. |
| 6739 locs->set_in(1, locs->in(0).IsConstant() | 6707 locs->set_in(1, locs->in(0).IsConstant() |
| 6740 ? Location::RequiresRegister() | 6708 ? Location::RequiresRegister() |
| 6741 : Location::RegisterOrConstant(right())); | 6709 : Location::RegisterOrConstant(right())); |
| 6742 locs->set_out(0, Location::RequiresRegister()); | 6710 locs->set_out(0, Location::RequiresRegister()); |
| 6743 return locs; | 6711 return locs; |
| 6744 } | 6712 } |
| 6745 | 6713 |
| 6746 | 6714 |
| 6747 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 6715 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 6748 BranchLabels labels) { | 6716 BranchLabels labels) { |
| 6749 Location left = locs()->in(0); | 6717 Location left = locs()->in(0); |
| 6750 Location right = locs()->in(1); | 6718 Location right = locs()->in(1); |
| 6751 ASSERT(!left.IsConstant() || !right.IsConstant()); | 6719 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 6752 Condition true_condition; | 6720 Condition true_condition; |
| 6753 if (left.IsConstant()) { | 6721 if (left.IsConstant()) { |
| 6754 true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), | 6722 true_condition = compiler->EmitEqualityRegConstCompare( |
| 6755 left.constant(), | 6723 right.reg(), left.constant(), needs_number_check(), token_pos()); |
| 6756 needs_number_check(), | |
| 6757 token_pos()); | |
| 6758 } else if (right.IsConstant()) { | 6724 } else if (right.IsConstant()) { |
| 6759 true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), | 6725 true_condition = compiler->EmitEqualityRegConstCompare( |
| 6760 right.constant(), | 6726 left.reg(), right.constant(), needs_number_check(), token_pos()); |
| 6761 needs_number_check(), | |
| 6762 token_pos()); | |
| 6763 } else { | 6727 } else { |
| 6764 true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), | 6728 true_condition = compiler->EmitEqualityRegRegCompare( |
| 6765 right.reg(), | 6729 left.reg(), right.reg(), needs_number_check(), token_pos()); |
| 6766 needs_number_check(), | |
| 6767 token_pos()); | |
| 6768 } | 6730 } |
| 6769 if (kind() != Token::kEQ_STRICT) { | 6731 if (kind() != Token::kEQ_STRICT) { |
| 6770 ASSERT(kind() == Token::kNE_STRICT); | 6732 ASSERT(kind() == Token::kNE_STRICT); |
| 6771 true_condition = NegateCondition(true_condition); | 6733 true_condition = NegateCondition(true_condition); |
| 6772 } | 6734 } |
| 6773 return true_condition; | 6735 return true_condition; |
| 6774 } | 6736 } |
| 6775 | 6737 |
| 6776 | 6738 |
| 6777 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6739 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6778 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 6740 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 6779 | 6741 |
| 6780 Label is_true, is_false; | 6742 Label is_true, is_false; |
| 6781 BranchLabels labels = { &is_true, &is_false, &is_false }; | 6743 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 6782 Condition true_condition = EmitComparisonCode(compiler, labels); | 6744 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 6783 EmitBranchOnCondition(compiler, true_condition, labels); | 6745 EmitBranchOnCondition(compiler, true_condition, labels); |
| 6784 | 6746 |
| 6785 Register result = locs()->out(0).reg(); | 6747 Register result = locs()->out(0).reg(); |
| 6786 Label done; | 6748 Label done; |
| 6787 __ Bind(&is_false); | 6749 __ Bind(&is_false); |
| 6788 __ LoadObject(result, Bool::False()); | 6750 __ LoadObject(result, Bool::False()); |
| 6789 __ jmp(&done, Assembler::kNearJump); | 6751 __ jmp(&done, Assembler::kNearJump); |
| 6790 __ Bind(&is_true); | 6752 __ Bind(&is_true); |
| 6791 __ LoadObject(result, Bool::True()); | 6753 __ LoadObject(result, Bool::True()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 6820 | 6782 |
| 6821 | 6783 |
| 6822 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6784 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6823 ASSERT(locs()->out(0).reg() == EDX); | 6785 ASSERT(locs()->out(0).reg() == EDX); |
| 6824 | 6786 |
| 6825 // Clear upper part of the out register. We are going to use setcc on it | 6787 // Clear upper part of the out register. We are going to use setcc on it |
| 6826 // which is a byte move. | 6788 // which is a byte move. |
| 6827 __ xorl(EDX, EDX); | 6789 __ xorl(EDX, EDX); |
| 6828 | 6790 |
| 6829 // Emit comparison code. This must not overwrite the result register. | 6791 // Emit comparison code. This must not overwrite the result register. |
| 6830 BranchLabels labels = { NULL, NULL, NULL }; | 6792 BranchLabels labels = {NULL, NULL, NULL}; |
| 6831 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 6793 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 6832 | 6794 |
| 6833 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 6795 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 6834 | 6796 |
| 6835 intptr_t true_value = if_true_; | 6797 intptr_t true_value = if_true_; |
| 6836 intptr_t false_value = if_false_; | 6798 intptr_t false_value = if_false_; |
| 6837 | 6799 |
| 6838 if (is_power_of_two_kind) { | 6800 if (is_power_of_two_kind) { |
| 6839 if (true_value == 0) { | 6801 if (true_value == 0) { |
| 6840 // We need to have zero in EDX on true_condition. | 6802 // We need to have zero in EDX on true_condition. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 6852 } | 6814 } |
| 6853 | 6815 |
| 6854 __ setcc(true_condition, DL); | 6816 __ setcc(true_condition, DL); |
| 6855 | 6817 |
| 6856 if (is_power_of_two_kind) { | 6818 if (is_power_of_two_kind) { |
| 6857 const intptr_t shift = | 6819 const intptr_t shift = |
| 6858 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 6820 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| 6859 __ shll(EDX, Immediate(shift + kSmiTagSize)); | 6821 __ shll(EDX, Immediate(shift + kSmiTagSize)); |
| 6860 } else { | 6822 } else { |
| 6861 __ decl(EDX); | 6823 __ decl(EDX); |
| 6862 __ andl(EDX, Immediate( | 6824 __ andl(EDX, |
| 6863 Smi::RawValue(true_value) - Smi::RawValue(false_value))); | 6825 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); |
| 6864 if (false_value != 0) { | 6826 if (false_value != 0) { |
| 6865 __ addl(EDX, Immediate(Smi::RawValue(false_value))); | 6827 __ addl(EDX, Immediate(Smi::RawValue(false_value))); |
| 6866 } | 6828 } |
| 6867 } | 6829 } |
| 6868 } | 6830 } |
| 6869 | 6831 |
| 6870 | 6832 |
| 6871 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 6833 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
| 6872 bool opt) const { | 6834 bool opt) const { |
| 6873 const intptr_t kNumInputs = 1; | 6835 const intptr_t kNumInputs = 1; |
| 6874 const intptr_t kNumTemps = 0; | 6836 const intptr_t kNumTemps = 0; |
| 6875 LocationSummary* summary = new(zone) LocationSummary( | 6837 LocationSummary* summary = new (zone) |
| 6876 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6838 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6877 summary->set_in(0, Location::RegisterLocation(EAX)); // Function. | 6839 summary->set_in(0, Location::RegisterLocation(EAX)); // Function. |
| 6878 summary->set_out(0, Location::RegisterLocation(EAX)); | 6840 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 6879 return summary; | 6841 return summary; |
| 6880 } | 6842 } |
| 6881 | 6843 |
| 6882 | 6844 |
| 6883 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6845 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6884 // Load arguments descriptors. | 6846 // Load arguments descriptors. |
| 6885 intptr_t argument_count = ArgumentCount(); | 6847 intptr_t argument_count = ArgumentCount(); |
| 6886 const Array& arguments_descriptor = | 6848 const Array& arguments_descriptor = Array::ZoneHandle( |
| 6887 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 6849 ArgumentsDescriptor::New(argument_count, argument_names())); |
| 6888 argument_names())); | |
| 6889 __ LoadObject(EDX, arguments_descriptor); | 6850 __ LoadObject(EDX, arguments_descriptor); |
| 6890 | 6851 |
| 6891 // EBX: Code (compiled code or lazy compile stub). | 6852 // EBX: Code (compiled code or lazy compile stub). |
| 6892 ASSERT(locs()->in(0).reg() == EAX); | 6853 ASSERT(locs()->in(0).reg() == EAX); |
| 6893 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); | 6854 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); |
| 6894 | 6855 |
| 6895 // EAX: Function. | 6856 // EAX: Function. |
| 6896 // EDX: Arguments descriptor array. | 6857 // EDX: Arguments descriptor array. |
| 6897 // ECX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 6858 // ECX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |
| 6898 __ xorl(ECX, ECX); | 6859 __ xorl(ECX, ECX); |
| 6899 __ call(EBX); | 6860 __ call(EBX); |
| 6900 compiler->RecordSafepoint(locs()); | 6861 compiler->RecordSafepoint(locs()); |
| 6901 // Marks either the continuation point in unoptimized code or the | 6862 // Marks either the continuation point in unoptimized code or the |
| 6902 // deoptimization point in optimized code, after call. | 6863 // deoptimization point in optimized code, after call. |
| 6903 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); | 6864 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); |
| 6904 if (compiler->is_optimizing()) { | 6865 if (compiler->is_optimizing()) { |
| 6905 compiler->AddDeoptIndexAtCall(deopt_id_after); | 6866 compiler->AddDeoptIndexAtCall(deopt_id_after); |
| 6906 } | 6867 } |
| 6907 // Add deoptimization continuation point after the call and before the | 6868 // Add deoptimization continuation point after the call and before the |
| 6908 // arguments are removed. | 6869 // arguments are removed. |
| 6909 // In optimized code this descriptor is needed for exception handling. | 6870 // In optimized code this descriptor is needed for exception handling. |
| 6910 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 6871 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
| 6911 deopt_id_after, | |
| 6912 token_pos()); | 6872 token_pos()); |
| 6913 __ Drop(argument_count); | 6873 __ Drop(argument_count); |
| 6914 } | 6874 } |
| 6915 | 6875 |
| 6916 | 6876 |
| 6917 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 6877 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
| 6918 bool opt) const { | 6878 bool opt) const { |
| 6919 return LocationSummary::Make(zone, | 6879 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
| 6920 1, | |
| 6921 Location::RequiresRegister(), | |
| 6922 LocationSummary::kNoCall); | 6880 LocationSummary::kNoCall); |
| 6923 } | 6881 } |
| 6924 | 6882 |
| 6925 | 6883 |
| 6926 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6884 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6927 Register value = locs()->in(0).reg(); | 6885 Register value = locs()->in(0).reg(); |
| 6928 Register result = locs()->out(0).reg(); | 6886 Register result = locs()->out(0).reg(); |
| 6929 | 6887 |
| 6930 Label done; | 6888 Label done; |
| 6931 __ LoadObject(result, Bool::True()); | 6889 __ LoadObject(result, Bool::True()); |
| 6932 __ CompareRegisters(result, value); | 6890 __ CompareRegisters(result, value); |
| 6933 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 6891 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 6934 __ LoadObject(result, Bool::False()); | 6892 __ LoadObject(result, Bool::False()); |
| 6935 __ Bind(&done); | 6893 __ Bind(&done); |
| 6936 } | 6894 } |
| 6937 | 6895 |
| 6938 | 6896 |
| 6939 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 6897 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
| 6940 bool opt) const { | 6898 bool opt) const { |
| 6941 return MakeCallSummary(zone); | 6899 return MakeCallSummary(zone); |
| 6942 } | 6900 } |
| 6943 | 6901 |
| 6944 | 6902 |
| 6945 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6903 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6946 const Code& stub = Code::ZoneHandle( | 6904 const Code& stub = Code::ZoneHandle( |
| 6947 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 6905 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
| 6948 const StubEntry stub_entry(stub); | 6906 const StubEntry stub_entry(stub); |
| 6949 compiler->GenerateCall(token_pos(), | 6907 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
| 6950 stub_entry, | |
| 6951 RawPcDescriptors::kOther, | |
| 6952 locs()); | 6908 locs()); |
| 6953 compiler->AddStubCallTarget(stub); | 6909 compiler->AddStubCallTarget(stub); |
| 6954 __ Drop(ArgumentCount()); // Discard arguments. | 6910 __ Drop(ArgumentCount()); // Discard arguments. |
| 6955 } | 6911 } |
| 6956 | 6912 |
| 6957 | 6913 |
| 6958 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6914 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6959 ASSERT(!compiler->is_optimizing()); | 6915 ASSERT(!compiler->is_optimizing()); |
| 6960 compiler->GenerateCall(token_pos(), | 6916 compiler->GenerateCall(token_pos(), *StubCode::DebugStepCheck_entry(), |
| 6961 *StubCode::DebugStepCheck_entry(), | 6917 stub_kind_, locs()); |
| 6962 stub_kind_, | |
| 6963 locs()); | |
| 6964 } | 6918 } |
| 6965 | 6919 |
| 6966 | 6920 |
| 6967 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( | 6921 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone, |
| 6968 Zone* zone, bool opt) const { | 6922 bool opt) const { |
| 6969 const intptr_t kNumInputs = 1; | 6923 const intptr_t kNumInputs = 1; |
| 6970 const intptr_t kNumTemps = 0; | 6924 const intptr_t kNumTemps = 0; |
| 6971 LocationSummary* locs = new(zone) LocationSummary( | 6925 LocationSummary* locs = new (zone) |
| 6972 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6926 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6973 locs->set_in(0, Location::RegisterLocation(EAX)); | 6927 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 6974 locs->set_out(0, Location::RegisterLocation(EAX)); | 6928 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 6975 return locs; | 6929 return locs; |
| 6976 } | 6930 } |
| 6977 | 6931 |
| 6978 | 6932 |
| 6979 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6933 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6980 const Register typed_data = locs()->in(0).reg(); | 6934 const Register typed_data = locs()->in(0).reg(); |
| 6981 const Register result = locs()->out(0).reg(); | 6935 const Register result = locs()->out(0).reg(); |
| 6982 __ PushObject(Object::null_object()); | 6936 __ PushObject(Object::null_object()); |
| 6983 __ pushl(typed_data); | 6937 __ pushl(typed_data); |
| 6984 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, | 6938 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
| 6985 deopt_id(), | 6939 kGrowRegExpStackRuntimeEntry, 1, locs()); |
| 6986 kGrowRegExpStackRuntimeEntry, | |
| 6987 1, | |
| 6988 locs()); | |
| 6989 __ Drop(1); | 6940 __ Drop(1); |
| 6990 __ popl(result); | 6941 __ popl(result); |
| 6991 } | 6942 } |
| 6992 | 6943 |
| 6993 | 6944 |
| 6994 } // namespace dart | 6945 } // namespace dart |
| 6995 | 6946 |
| 6996 #undef __ | 6947 #undef __ |
| 6997 | 6948 |
| 6998 #endif // defined TARGET_ARCH_IA32 | 6949 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |