| 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 18 matching lines...) Expand all Loading... |
| 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) | 33 LocationSummary* result = new (zone) |
| 34 LocationSummary(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 | |
| 40 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
| 41 bool opt) const { | 40 bool opt) const { |
| 42 const intptr_t kNumInputs = 1; | 41 const intptr_t kNumInputs = 1; |
| 43 const intptr_t kNumTemps = 0; | 42 const intptr_t kNumTemps = 0; |
| 44 LocationSummary* locs = new (zone) | 43 LocationSummary* locs = new (zone) |
| 45 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 44 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 46 locs->set_in(0, Location::AnyOrConstant(value())); | 45 locs->set_in(0, Location::AnyOrConstant(value())); |
| 47 return locs; | 46 return locs; |
| 48 } | 47 } |
| 49 | 48 |
| 50 | |
| 51 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 49 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 52 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 50 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 53 // where PushArgument is handled by BindInstr::EmitNativeCode. | 51 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 54 if (compiler->is_optimizing()) { | 52 if (compiler->is_optimizing()) { |
| 55 Location value = locs()->in(0); | 53 Location value = locs()->in(0); |
| 56 if (value.IsRegister()) { | 54 if (value.IsRegister()) { |
| 57 __ pushl(value.reg()); | 55 __ pushl(value.reg()); |
| 58 } else if (value.IsConstant()) { | 56 } else if (value.IsConstant()) { |
| 59 __ PushObject(value.constant()); | 57 __ PushObject(value.constant()); |
| 60 } else { | 58 } else { |
| 61 ASSERT(value.IsStackSlot()); | 59 ASSERT(value.IsStackSlot()); |
| 62 __ pushl(value.ToStackSlotAddress()); | 60 __ pushl(value.ToStackSlotAddress()); |
| 63 } | 61 } |
| 64 } | 62 } |
| 65 } | 63 } |
| 66 | 64 |
| 67 | |
| 68 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 65 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 69 const intptr_t kNumInputs = 1; | 66 const intptr_t kNumInputs = 1; |
| 70 const intptr_t kNumTemps = 0; | 67 const intptr_t kNumTemps = 0; |
| 71 LocationSummary* locs = new (zone) | 68 LocationSummary* locs = new (zone) |
| 72 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 69 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 73 locs->set_in(0, Location::RegisterLocation(EAX)); | 70 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 74 return locs; | 71 return locs; |
| 75 } | 72 } |
| 76 | 73 |
| 77 | |
| 78 // Attempt optimized compilation at return instruction instead of at the entry. | 74 // Attempt optimized compilation at return instruction instead of at the entry. |
| 79 // The entry needs to be patchable, no inlined objects are allowed in the area | 75 // The entry needs to be patchable, no inlined objects are allowed in the area |
| 80 // that will be overwritten by the patch instruction: a jump). | 76 // that will be overwritten by the patch instruction: a jump). |
| 81 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 77 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 82 Register result = locs()->in(0).reg(); | 78 Register result = locs()->in(0).reg(); |
| 83 ASSERT(result == EAX); | 79 ASSERT(result == EAX); |
| 84 | 80 |
| 85 if (compiler->intrinsic_mode()) { | 81 if (compiler->intrinsic_mode()) { |
| 86 // Intrinsics don't have a frame. | 82 // Intrinsics don't have a frame. |
| 87 __ ret(); | 83 __ ret(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 98 __ subl(EDI, EBP); | 94 __ subl(EDI, EBP); |
| 99 __ cmpl(EDI, Immediate(fp_sp_dist)); | 95 __ cmpl(EDI, Immediate(fp_sp_dist)); |
| 100 __ j(EQUAL, &done, Assembler::kNearJump); | 96 __ j(EQUAL, &done, Assembler::kNearJump); |
| 101 __ int3(); | 97 __ int3(); |
| 102 __ Bind(&done); | 98 __ Bind(&done); |
| 103 #endif | 99 #endif |
| 104 __ LeaveFrame(); | 100 __ LeaveFrame(); |
| 105 __ ret(); | 101 __ ret(); |
| 106 } | 102 } |
| 107 | 103 |
| 108 | |
| 109 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 104 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
| 110 bool opt) const { | 105 bool opt) const { |
| 111 const intptr_t kNumInputs = 0; | 106 const intptr_t kNumInputs = 0; |
| 112 const intptr_t stack_index = (local().index() < 0) | 107 const intptr_t stack_index = (local().index() < 0) |
| 113 ? kFirstLocalSlotFromFp - local().index() | 108 ? kFirstLocalSlotFromFp - local().index() |
| 114 : kParamEndSlotFromFp - local().index(); | 109 : kParamEndSlotFromFp - local().index(); |
| 115 return LocationSummary::Make(zone, kNumInputs, | 110 return LocationSummary::Make(zone, kNumInputs, |
| 116 Location::StackSlot(stack_index), | 111 Location::StackSlot(stack_index), |
| 117 LocationSummary::kNoCall); | 112 LocationSummary::kNoCall); |
| 118 } | 113 } |
| 119 | 114 |
| 120 | |
| 121 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 115 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 122 ASSERT(!compiler->is_optimizing()); | 116 ASSERT(!compiler->is_optimizing()); |
| 123 // Nothing to do. | 117 // Nothing to do. |
| 124 } | 118 } |
| 125 | 119 |
| 126 | |
| 127 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 120 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
| 128 bool opt) const { | 121 bool opt) const { |
| 129 const intptr_t kNumInputs = 1; | 122 const intptr_t kNumInputs = 1; |
| 130 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), | 123 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
| 131 LocationSummary::kNoCall); | 124 LocationSummary::kNoCall); |
| 132 } | 125 } |
| 133 | 126 |
| 134 | |
| 135 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 127 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 136 Register value = locs()->in(0).reg(); | 128 Register value = locs()->in(0).reg(); |
| 137 Register result = locs()->out(0).reg(); | 129 Register result = locs()->out(0).reg(); |
| 138 ASSERT(result == value); // Assert that register assignment is correct. | 130 ASSERT(result == value); // Assert that register assignment is correct. |
| 139 __ movl(Address(EBP, local().index() * kWordSize), value); | 131 __ movl(Address(EBP, local().index() * kWordSize), value); |
| 140 } | 132 } |
| 141 | 133 |
| 142 | |
| 143 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 134 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
| 144 bool opt) const { | 135 bool opt) const { |
| 145 const intptr_t kNumInputs = 0; | 136 const intptr_t kNumInputs = 0; |
| 146 return LocationSummary::Make(zone, kNumInputs, | 137 return LocationSummary::Make(zone, kNumInputs, |
| 147 Assembler::IsSafe(value()) | 138 Assembler::IsSafe(value()) |
| 148 ? Location::Constant(this) | 139 ? Location::Constant(this) |
| 149 : Location::RequiresRegister(), | 140 : Location::RequiresRegister(), |
| 150 LocationSummary::kNoCall); | 141 LocationSummary::kNoCall); |
| 151 } | 142 } |
| 152 | 143 |
| 153 | |
| 154 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 144 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 155 // The register allocator drops constant definitions that have no uses. | 145 // The register allocator drops constant definitions that have no uses. |
| 156 Location out = locs()->out(0); | 146 Location out = locs()->out(0); |
| 157 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); | 147 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); |
| 158 if (out.IsRegister()) { | 148 if (out.IsRegister()) { |
| 159 Register result = out.reg(); | 149 Register result = out.reg(); |
| 160 __ LoadObjectSafely(result, value()); | 150 __ LoadObjectSafely(result, value()); |
| 161 } | 151 } |
| 162 } | 152 } |
| 163 | 153 |
| 164 | |
| 165 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 154 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
| 166 bool opt) const { | 155 bool opt) const { |
| 167 const intptr_t kNumInputs = 0; | 156 const intptr_t kNumInputs = 0; |
| 168 const intptr_t kNumTemps = | 157 const intptr_t kNumTemps = |
| 169 (constant_address() == 0) && (representation() != kUnboxedInt32) ? 1 : 0; | 158 (constant_address() == 0) && (representation() != kUnboxedInt32) ? 1 : 0; |
| 170 LocationSummary* locs = new (zone) | 159 LocationSummary* locs = new (zone) |
| 171 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 160 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 172 if (representation() == kUnboxedDouble) { | 161 if (representation() == kUnboxedDouble) { |
| 173 locs->set_out(0, Location::RequiresFpuRegister()); | 162 locs->set_out(0, Location::RequiresFpuRegister()); |
| 174 } else { | 163 } else { |
| 175 ASSERT(representation() == kUnboxedInt32); | 164 ASSERT(representation() == kUnboxedInt32); |
| 176 locs->set_out(0, Location::RequiresRegister()); | 165 locs->set_out(0, Location::RequiresRegister()); |
| 177 } | 166 } |
| 178 if (kNumTemps == 1) { | 167 if (kNumTemps == 1) { |
| 179 locs->set_temp(0, Location::RequiresRegister()); | 168 locs->set_temp(0, Location::RequiresRegister()); |
| 180 } | 169 } |
| 181 return locs; | 170 return locs; |
| 182 } | 171 } |
| 183 | 172 |
| 184 | |
| 185 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 173 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 186 // The register allocator drops constant definitions that have no uses. | 174 // The register allocator drops constant definitions that have no uses. |
| 187 if (!locs()->out(0).IsInvalid()) { | 175 if (!locs()->out(0).IsInvalid()) { |
| 188 switch (representation()) { | 176 switch (representation()) { |
| 189 case kUnboxedDouble: { | 177 case kUnboxedDouble: { |
| 190 XmmRegister result = locs()->out(0).fpu_reg(); | 178 XmmRegister result = locs()->out(0).fpu_reg(); |
| 191 if (constant_address() == 0) { | 179 if (constant_address() == 0) { |
| 192 Register boxed = locs()->temp(0).reg(); | 180 Register boxed = locs()->temp(0).reg(); |
| 193 __ LoadObjectSafely(boxed, value()); | 181 __ LoadObjectSafely(boxed, value()); |
| 194 __ movsd(result, FieldAddress(boxed, Double::value_offset())); | 182 __ movsd(result, FieldAddress(boxed, Double::value_offset())); |
| 195 } else if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 183 } else if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |
| 196 __ xorps(result, result); | 184 __ xorps(result, result); |
| 197 } else { | 185 } else { |
| 198 __ movsd(result, Address::Absolute(constant_address())); | 186 __ movsd(result, Address::Absolute(constant_address())); |
| 199 } | 187 } |
| 200 break; | 188 break; |
| 201 } | 189 } |
| 202 case kUnboxedInt32: | 190 case kUnboxedInt32: |
| 203 __ movl(locs()->out(0).reg(), Immediate(Smi::Cast(value()).Value())); | 191 __ movl(locs()->out(0).reg(), Immediate(Smi::Cast(value()).Value())); |
| 204 break; | 192 break; |
| 205 default: | 193 default: |
| 206 UNREACHABLE(); | 194 UNREACHABLE(); |
| 207 } | 195 } |
| 208 } | 196 } |
| 209 } | 197 } |
| 210 | 198 |
| 211 | |
| 212 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 199 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
| 213 bool opt) const { | 200 bool opt) const { |
| 214 const intptr_t kNumInputs = 3; | 201 const intptr_t kNumInputs = 3; |
| 215 const intptr_t kNumTemps = 0; | 202 const intptr_t kNumTemps = 0; |
| 216 LocationSummary* summary = new (zone) | 203 LocationSummary* summary = new (zone) |
| 217 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 204 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 218 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. | 205 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. |
| 219 summary->set_in(1, Location::RegisterLocation(EDX)); // Instant. type args. | 206 summary->set_in(1, Location::RegisterLocation(EDX)); // Instant. type args. |
| 220 summary->set_in(2, Location::RegisterLocation(ECX)); // Function type args. | 207 summary->set_in(2, Location::RegisterLocation(ECX)); // Function type args. |
| 221 summary->set_out(0, Location::RegisterLocation(EAX)); | 208 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 222 return summary; | 209 return summary; |
| 223 } | 210 } |
| 224 | 211 |
| 225 | |
| 226 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 212 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
| 227 bool opt) const { | 213 bool opt) const { |
| 228 const intptr_t kNumInputs = 1; | 214 const intptr_t kNumInputs = 1; |
| 229 const intptr_t kNumTemps = 0; | 215 const intptr_t kNumTemps = 0; |
| 230 LocationSummary* locs = new (zone) | 216 LocationSummary* locs = new (zone) |
| 231 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 217 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 232 locs->set_in(0, Location::RegisterLocation(EAX)); | 218 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 233 locs->set_out(0, Location::RegisterLocation(EAX)); | 219 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 234 return locs; | 220 return locs; |
| 235 } | 221 } |
| 236 | 222 |
| 237 | |
| 238 static void EmitAssertBoolean(Register reg, | 223 static void EmitAssertBoolean(Register reg, |
| 239 TokenPosition token_pos, | 224 TokenPosition token_pos, |
| 240 intptr_t deopt_id, | 225 intptr_t deopt_id, |
| 241 LocationSummary* locs, | 226 LocationSummary* locs, |
| 242 FlowGraphCompiler* compiler) { | 227 FlowGraphCompiler* compiler) { |
| 243 // Check that the type of the value is allowed in conditional context. | 228 // Check that the type of the value is allowed in conditional context. |
| 244 // Call the runtime if the object is not bool::true or bool::false. | 229 // Call the runtime if the object is not bool::true or bool::false. |
| 245 ASSERT(locs->always_calls()); | 230 ASSERT(locs->always_calls()); |
| 246 Label done; | 231 Label done; |
| 247 | 232 |
| 248 if (Isolate::Current()->type_checks()) { | 233 if (Isolate::Current()->type_checks()) { |
| 249 __ CompareObject(reg, Bool::True()); | 234 __ CompareObject(reg, Bool::True()); |
| 250 __ j(EQUAL, &done, Assembler::kNearJump); | 235 __ j(EQUAL, &done, Assembler::kNearJump); |
| 251 __ CompareObject(reg, Bool::False()); | 236 __ CompareObject(reg, Bool::False()); |
| 252 __ j(EQUAL, &done, Assembler::kNearJump); | 237 __ j(EQUAL, &done, Assembler::kNearJump); |
| 253 } else { | 238 } else { |
| 254 ASSERT(Isolate::Current()->asserts()); | 239 ASSERT(Isolate::Current()->asserts()); |
| 255 __ CompareObject(reg, Object::null_instance()); | 240 __ CompareObject(reg, Object::null_instance()); |
| 256 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 241 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 257 } | 242 } |
| 258 | 243 |
| 259 __ pushl(reg); // Push the source object. | 244 __ pushl(reg); // Push the source object. |
| 260 compiler->GenerateRuntimeCall(token_pos, deopt_id, | 245 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
| 261 kNonBoolTypeErrorRuntimeEntry, 1, locs); | 246 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
| 262 // We should never return here. | 247 // We should never return here. |
| 263 __ int3(); | 248 __ int3(); |
| 264 __ Bind(&done); | 249 __ Bind(&done); |
| 265 } | 250 } |
| 266 | 251 |
| 267 | |
| 268 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 252 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 269 Register obj = locs()->in(0).reg(); | 253 Register obj = locs()->in(0).reg(); |
| 270 Register result = locs()->out(0).reg(); | 254 Register result = locs()->out(0).reg(); |
| 271 | 255 |
| 272 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 256 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 273 ASSERT(obj == result); | 257 ASSERT(obj == result); |
| 274 } | 258 } |
| 275 | 259 |
| 276 | |
| 277 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 260 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 278 switch (kind) { | 261 switch (kind) { |
| 279 case Token::kEQ: | 262 case Token::kEQ: |
| 280 return EQUAL; | 263 return EQUAL; |
| 281 case Token::kNE: | 264 case Token::kNE: |
| 282 return NOT_EQUAL; | 265 return NOT_EQUAL; |
| 283 case Token::kLT: | 266 case Token::kLT: |
| 284 return LESS; | 267 return LESS; |
| 285 case Token::kGT: | 268 case Token::kGT: |
| 286 return GREATER; | 269 return GREATER; |
| 287 case Token::kLTE: | 270 case Token::kLTE: |
| 288 return LESS_EQUAL; | 271 return LESS_EQUAL; |
| 289 case Token::kGTE: | 272 case Token::kGTE: |
| 290 return GREATER_EQUAL; | 273 return GREATER_EQUAL; |
| 291 default: | 274 default: |
| 292 UNREACHABLE(); | 275 UNREACHABLE(); |
| 293 return OVERFLOW; | 276 return OVERFLOW; |
| 294 } | 277 } |
| 295 } | 278 } |
| 296 | 279 |
| 297 | |
| 298 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 280 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
| 299 bool opt) const { | 281 bool opt) const { |
| 300 const intptr_t kNumInputs = 2; | 282 const intptr_t kNumInputs = 2; |
| 301 if (operation_cid() == kMintCid) { | 283 if (operation_cid() == kMintCid) { |
| 302 const intptr_t kNumTemps = 0; | 284 const intptr_t kNumTemps = 0; |
| 303 LocationSummary* locs = new (zone) | 285 LocationSummary* locs = new (zone) |
| 304 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 286 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 305 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 287 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 306 Location::RequiresRegister())); | 288 Location::RequiresRegister())); |
| 307 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 289 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| (...skipping 21 matching lines...) Expand all Loading... |
| 329 locs->set_in(1, locs->in(0).IsConstant() | 311 locs->set_in(1, locs->in(0).IsConstant() |
| 330 ? Location::RequiresRegister() | 312 ? Location::RequiresRegister() |
| 331 : Location::RegisterOrConstant(right())); | 313 : Location::RegisterOrConstant(right())); |
| 332 locs->set_out(0, Location::RequiresRegister()); | 314 locs->set_out(0, Location::RequiresRegister()); |
| 333 return locs; | 315 return locs; |
| 334 } | 316 } |
| 335 UNREACHABLE(); | 317 UNREACHABLE(); |
| 336 return NULL; | 318 return NULL; |
| 337 } | 319 } |
| 338 | 320 |
| 339 | |
| 340 static void LoadValueCid(FlowGraphCompiler* compiler, | 321 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 341 Register value_cid_reg, | 322 Register value_cid_reg, |
| 342 Register value_reg, | 323 Register value_reg, |
| 343 Label* value_is_smi = NULL) { | 324 Label* value_is_smi = NULL) { |
| 344 Label done; | 325 Label done; |
| 345 if (value_is_smi == NULL) { | 326 if (value_is_smi == NULL) { |
| 346 __ movl(value_cid_reg, Immediate(kSmiCid)); | 327 __ movl(value_cid_reg, Immediate(kSmiCid)); |
| 347 } | 328 } |
| 348 __ testl(value_reg, Immediate(kSmiTagMask)); | 329 __ testl(value_reg, Immediate(kSmiTagMask)); |
| 349 if (value_is_smi == NULL) { | 330 if (value_is_smi == NULL) { |
| 350 __ j(ZERO, &done, Assembler::kNearJump); | 331 __ j(ZERO, &done, Assembler::kNearJump); |
| 351 } else { | 332 } else { |
| 352 __ j(ZERO, value_is_smi); | 333 __ j(ZERO, value_is_smi); |
| 353 } | 334 } |
| 354 __ LoadClassId(value_cid_reg, value_reg); | 335 __ LoadClassId(value_cid_reg, value_reg); |
| 355 __ Bind(&done); | 336 __ Bind(&done); |
| 356 } | 337 } |
| 357 | 338 |
| 358 | |
| 359 static Condition FlipCondition(Condition condition) { | 339 static Condition FlipCondition(Condition condition) { |
| 360 switch (condition) { | 340 switch (condition) { |
| 361 case EQUAL: | 341 case EQUAL: |
| 362 return EQUAL; | 342 return EQUAL; |
| 363 case NOT_EQUAL: | 343 case NOT_EQUAL: |
| 364 return NOT_EQUAL; | 344 return NOT_EQUAL; |
| 365 case LESS: | 345 case LESS: |
| 366 return GREATER; | 346 return GREATER; |
| 367 case LESS_EQUAL: | 347 case LESS_EQUAL: |
| 368 return GREATER_EQUAL; | 348 return GREATER_EQUAL; |
| 369 case GREATER: | 349 case GREATER: |
| 370 return LESS; | 350 return LESS; |
| 371 case GREATER_EQUAL: | 351 case GREATER_EQUAL: |
| 372 return LESS_EQUAL; | 352 return LESS_EQUAL; |
| 373 case BELOW: | 353 case BELOW: |
| 374 return ABOVE; | 354 return ABOVE; |
| 375 case BELOW_EQUAL: | 355 case BELOW_EQUAL: |
| 376 return ABOVE_EQUAL; | 356 return ABOVE_EQUAL; |
| 377 case ABOVE: | 357 case ABOVE: |
| 378 return BELOW; | 358 return BELOW; |
| 379 case ABOVE_EQUAL: | 359 case ABOVE_EQUAL: |
| 380 return BELOW_EQUAL; | 360 return BELOW_EQUAL; |
| 381 default: | 361 default: |
| 382 UNIMPLEMENTED(); | 362 UNIMPLEMENTED(); |
| 383 return EQUAL; | 363 return EQUAL; |
| 384 } | 364 } |
| 385 } | 365 } |
| 386 | 366 |
| 387 | |
| 388 static Condition NegateCondition(Condition condition) { | 367 static Condition NegateCondition(Condition condition) { |
| 389 switch (condition) { | 368 switch (condition) { |
| 390 case EQUAL: | 369 case EQUAL: |
| 391 return NOT_EQUAL; | 370 return NOT_EQUAL; |
| 392 case NOT_EQUAL: | 371 case NOT_EQUAL: |
| 393 return EQUAL; | 372 return EQUAL; |
| 394 case LESS: | 373 case LESS: |
| 395 return GREATER_EQUAL; | 374 return GREATER_EQUAL; |
| 396 case LESS_EQUAL: | 375 case LESS_EQUAL: |
| 397 return GREATER; | 376 return GREATER; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 410 case PARITY_ODD: | 389 case PARITY_ODD: |
| 411 return PARITY_EVEN; | 390 return PARITY_EVEN; |
| 412 case PARITY_EVEN: | 391 case PARITY_EVEN: |
| 413 return PARITY_ODD; | 392 return PARITY_ODD; |
| 414 default: | 393 default: |
| 415 UNIMPLEMENTED(); | 394 UNIMPLEMENTED(); |
| 416 return EQUAL; | 395 return EQUAL; |
| 417 } | 396 } |
| 418 } | 397 } |
| 419 | 398 |
| 420 | |
| 421 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 399 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 422 Condition true_condition, | 400 Condition true_condition, |
| 423 BranchLabels labels) { | 401 BranchLabels labels) { |
| 424 if (labels.fall_through == labels.false_label) { | 402 if (labels.fall_through == labels.false_label) { |
| 425 // If the next block is the false successor, fall through to it. | 403 // If the next block is the false successor, fall through to it. |
| 426 __ j(true_condition, labels.true_label); | 404 __ j(true_condition, labels.true_label); |
| 427 } else { | 405 } else { |
| 428 // If the next block is not the false successor, branch to it. | 406 // If the next block is not the false successor, branch to it. |
| 429 Condition false_condition = NegateCondition(true_condition); | 407 Condition false_condition = NegateCondition(true_condition); |
| 430 __ j(false_condition, labels.false_label); | 408 __ j(false_condition, labels.false_label); |
| 431 | 409 |
| 432 // Fall through or jump to the true successor. | 410 // Fall through or jump to the true successor. |
| 433 if (labels.fall_through != labels.true_label) { | 411 if (labels.fall_through != labels.true_label) { |
| 434 __ jmp(labels.true_label); | 412 __ jmp(labels.true_label); |
| 435 } | 413 } |
| 436 } | 414 } |
| 437 } | 415 } |
| 438 | 416 |
| 439 | |
| 440 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 417 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 441 const LocationSummary& locs, | 418 const LocationSummary& locs, |
| 442 Token::Kind kind, | 419 Token::Kind kind, |
| 443 BranchLabels labels) { | 420 BranchLabels labels) { |
| 444 Location left = locs.in(0); | 421 Location left = locs.in(0); |
| 445 Location right = locs.in(1); | 422 Location right = locs.in(1); |
| 446 ASSERT(!left.IsConstant() || !right.IsConstant()); | 423 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 447 | 424 |
| 448 Condition true_condition = TokenKindToSmiCondition(kind); | 425 Condition true_condition = TokenKindToSmiCondition(kind); |
| 449 | 426 |
| 450 if (left.IsConstant()) { | 427 if (left.IsConstant()) { |
| 451 __ CompareObject(right.reg(), left.constant()); | 428 __ CompareObject(right.reg(), left.constant()); |
| 452 true_condition = FlipCondition(true_condition); | 429 true_condition = FlipCondition(true_condition); |
| 453 } else if (right.IsConstant()) { | 430 } else if (right.IsConstant()) { |
| 454 __ CompareObject(left.reg(), right.constant()); | 431 __ CompareObject(left.reg(), right.constant()); |
| 455 } else if (right.IsStackSlot()) { | 432 } else if (right.IsStackSlot()) { |
| 456 __ cmpl(left.reg(), right.ToStackSlotAddress()); | 433 __ cmpl(left.reg(), right.ToStackSlotAddress()); |
| 457 } else { | 434 } else { |
| 458 __ cmpl(left.reg(), right.reg()); | 435 __ cmpl(left.reg(), right.reg()); |
| 459 } | 436 } |
| 460 return true_condition; | 437 return true_condition; |
| 461 } | 438 } |
| 462 | 439 |
| 463 | |
| 464 static Condition TokenKindToMintCondition(Token::Kind kind) { | 440 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 465 switch (kind) { | 441 switch (kind) { |
| 466 case Token::kEQ: | 442 case Token::kEQ: |
| 467 return EQUAL; | 443 return EQUAL; |
| 468 case Token::kNE: | 444 case Token::kNE: |
| 469 return NOT_EQUAL; | 445 return NOT_EQUAL; |
| 470 case Token::kLT: | 446 case Token::kLT: |
| 471 return LESS; | 447 return LESS; |
| 472 case Token::kGT: | 448 case Token::kGT: |
| 473 return GREATER; | 449 return GREATER; |
| 474 case Token::kLTE: | 450 case Token::kLTE: |
| 475 return LESS_EQUAL; | 451 return LESS_EQUAL; |
| 476 case Token::kGTE: | 452 case Token::kGTE: |
| 477 return GREATER_EQUAL; | 453 return GREATER_EQUAL; |
| 478 default: | 454 default: |
| 479 UNREACHABLE(); | 455 UNREACHABLE(); |
| 480 return OVERFLOW; | 456 return OVERFLOW; |
| 481 } | 457 } |
| 482 } | 458 } |
| 483 | 459 |
| 484 | |
| 485 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 460 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 486 const LocationSummary& locs, | 461 const LocationSummary& locs, |
| 487 Token::Kind kind, | 462 Token::Kind kind, |
| 488 BranchLabels labels) { | 463 BranchLabels labels) { |
| 489 ASSERT(Token::IsEqualityOperator(kind)); | 464 ASSERT(Token::IsEqualityOperator(kind)); |
| 490 PairLocation* left_pair = locs.in(0).AsPairLocation(); | 465 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
| 491 Register left1 = left_pair->At(0).reg(); | 466 Register left1 = left_pair->At(0).reg(); |
| 492 Register left2 = left_pair->At(1).reg(); | 467 Register left2 = left_pair->At(1).reg(); |
| 493 PairLocation* right_pair = locs.in(1).AsPairLocation(); | 468 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
| 494 Register right1 = right_pair->At(0).reg(); | 469 Register right1 = right_pair->At(0).reg(); |
| 495 Register right2 = right_pair->At(1).reg(); | 470 Register right2 = right_pair->At(1).reg(); |
| 496 Label done; | 471 Label done; |
| 497 // Compare lower. | 472 // Compare lower. |
| 498 __ cmpl(left1, right1); | 473 __ cmpl(left1, right1); |
| 499 __ j(NOT_EQUAL, &done); | 474 __ j(NOT_EQUAL, &done); |
| 500 // Lower is equal, compare upper. | 475 // Lower is equal, compare upper. |
| 501 __ cmpl(left2, right2); | 476 __ cmpl(left2, right2); |
| 502 __ Bind(&done); | 477 __ Bind(&done); |
| 503 Condition true_condition = TokenKindToMintCondition(kind); | 478 Condition true_condition = TokenKindToMintCondition(kind); |
| 504 return true_condition; | 479 return true_condition; |
| 505 } | 480 } |
| 506 | 481 |
| 507 | |
| 508 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 482 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
| 509 const LocationSummary& locs, | 483 const LocationSummary& locs, |
| 510 Token::Kind kind, | 484 Token::Kind kind, |
| 511 BranchLabels labels) { | 485 BranchLabels labels) { |
| 512 PairLocation* left_pair = locs.in(0).AsPairLocation(); | 486 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
| 513 Register left1 = left_pair->At(0).reg(); | 487 Register left1 = left_pair->At(0).reg(); |
| 514 Register left2 = left_pair->At(1).reg(); | 488 Register left2 = left_pair->At(1).reg(); |
| 515 PairLocation* right_pair = locs.in(1).AsPairLocation(); | 489 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
| 516 Register right1 = right_pair->At(0).reg(); | 490 Register right1 = right_pair->At(0).reg(); |
| 517 Register right2 = right_pair->At(1).reg(); | 491 Register right2 = right_pair->At(1).reg(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 541 // Compare upper halves first. | 515 // Compare upper halves first. |
| 542 __ cmpl(left2, right2); | 516 __ cmpl(left2, right2); |
| 543 __ j(hi_cond, labels.true_label); | 517 __ j(hi_cond, labels.true_label); |
| 544 __ j(FlipCondition(hi_cond), labels.false_label); | 518 __ j(FlipCondition(hi_cond), labels.false_label); |
| 545 | 519 |
| 546 // If upper is equal, compare lower half. | 520 // If upper is equal, compare lower half. |
| 547 __ cmpl(left1, right1); | 521 __ cmpl(left1, right1); |
| 548 return lo_cond; | 522 return lo_cond; |
| 549 } | 523 } |
| 550 | 524 |
| 551 | |
| 552 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 525 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 553 switch (kind) { | 526 switch (kind) { |
| 554 case Token::kEQ: | 527 case Token::kEQ: |
| 555 return EQUAL; | 528 return EQUAL; |
| 556 case Token::kNE: | 529 case Token::kNE: |
| 557 return NOT_EQUAL; | 530 return NOT_EQUAL; |
| 558 case Token::kLT: | 531 case Token::kLT: |
| 559 return BELOW; | 532 return BELOW; |
| 560 case Token::kGT: | 533 case Token::kGT: |
| 561 return ABOVE; | 534 return ABOVE; |
| 562 case Token::kLTE: | 535 case Token::kLTE: |
| 563 return BELOW_EQUAL; | 536 return BELOW_EQUAL; |
| 564 case Token::kGTE: | 537 case Token::kGTE: |
| 565 return ABOVE_EQUAL; | 538 return ABOVE_EQUAL; |
| 566 default: | 539 default: |
| 567 UNREACHABLE(); | 540 UNREACHABLE(); |
| 568 return OVERFLOW; | 541 return OVERFLOW; |
| 569 } | 542 } |
| 570 } | 543 } |
| 571 | 544 |
| 572 | |
| 573 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 545 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 574 const LocationSummary& locs, | 546 const LocationSummary& locs, |
| 575 Token::Kind kind, | 547 Token::Kind kind, |
| 576 BranchLabels labels) { | 548 BranchLabels labels) { |
| 577 XmmRegister left = locs.in(0).fpu_reg(); | 549 XmmRegister left = locs.in(0).fpu_reg(); |
| 578 XmmRegister right = locs.in(1).fpu_reg(); | 550 XmmRegister right = locs.in(1).fpu_reg(); |
| 579 | 551 |
| 580 __ comisd(left, right); | 552 __ comisd(left, right); |
| 581 | 553 |
| 582 Condition true_condition = TokenKindToDoubleCondition(kind); | 554 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 583 Label* nan_result = | 555 Label* nan_result = |
| 584 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; | 556 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; |
| 585 __ j(PARITY_EVEN, nan_result); | 557 __ j(PARITY_EVEN, nan_result); |
| 586 return true_condition; | 558 return true_condition; |
| 587 } | 559 } |
| 588 | 560 |
| 589 | |
| 590 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 561 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 591 BranchLabels labels) { | 562 BranchLabels labels) { |
| 592 if (operation_cid() == kSmiCid) { | 563 if (operation_cid() == kSmiCid) { |
| 593 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 564 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 594 } else if (operation_cid() == kMintCid) { | 565 } else if (operation_cid() == kMintCid) { |
| 595 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels); | 566 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels); |
| 596 } else { | 567 } else { |
| 597 ASSERT(operation_cid() == kDoubleCid); | 568 ASSERT(operation_cid() == kDoubleCid); |
| 598 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 569 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 599 } | 570 } |
| 600 } | 571 } |
| 601 | 572 |
| 602 | |
| 603 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 573 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 604 Label is_true, is_false; | 574 Label is_true, is_false; |
| 605 BranchLabels labels = {&is_true, &is_false, &is_false}; | 575 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 606 Condition true_condition = EmitComparisonCode(compiler, labels); | 576 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 607 if (true_condition != INVALID_CONDITION) { | 577 if (true_condition != INVALID_CONDITION) { |
| 608 EmitBranchOnCondition(compiler, true_condition, labels); | 578 EmitBranchOnCondition(compiler, true_condition, labels); |
| 609 } | 579 } |
| 610 | 580 |
| 611 Register result = locs()->out(0).reg(); | 581 Register result = locs()->out(0).reg(); |
| 612 Label done; | 582 Label done; |
| 613 __ Bind(&is_false); | 583 __ Bind(&is_false); |
| 614 __ LoadObject(result, Bool::False()); | 584 __ LoadObject(result, Bool::False()); |
| 615 __ jmp(&done, Assembler::kNearJump); | 585 __ jmp(&done, Assembler::kNearJump); |
| 616 __ Bind(&is_true); | 586 __ Bind(&is_true); |
| 617 __ LoadObject(result, Bool::True()); | 587 __ LoadObject(result, Bool::True()); |
| 618 __ Bind(&done); | 588 __ Bind(&done); |
| 619 } | 589 } |
| 620 | 590 |
| 621 | |
| 622 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 591 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 623 BranchInstr* branch) { | 592 BranchInstr* branch) { |
| 624 BranchLabels labels = compiler->CreateBranchLabels(branch); | 593 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 625 Condition true_condition = EmitComparisonCode(compiler, labels); | 594 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 626 if (true_condition != INVALID_CONDITION) { | 595 if (true_condition != INVALID_CONDITION) { |
| 627 EmitBranchOnCondition(compiler, true_condition, labels); | 596 EmitBranchOnCondition(compiler, true_condition, labels); |
| 628 } | 597 } |
| 629 } | 598 } |
| 630 | 599 |
| 631 | |
| 632 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 600 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 633 const intptr_t kNumInputs = 2; | 601 const intptr_t kNumInputs = 2; |
| 634 const intptr_t kNumTemps = 0; | 602 const intptr_t kNumTemps = 0; |
| 635 LocationSummary* locs = new (zone) | 603 LocationSummary* locs = new (zone) |
| 636 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 604 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 637 locs->set_in(0, Location::RequiresRegister()); | 605 locs->set_in(0, Location::RequiresRegister()); |
| 638 // Only one input can be a constant operand. The case of two constant | 606 // Only one input can be a constant operand. The case of two constant |
| 639 // operands should be handled by constant propagation. | 607 // operands should be handled by constant propagation. |
| 640 locs->set_in(1, Location::RegisterOrConstant(right())); | 608 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 641 return locs; | 609 return locs; |
| 642 } | 610 } |
| 643 | 611 |
| 644 | |
| 645 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 612 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 646 BranchLabels labels) { | 613 BranchLabels labels) { |
| 647 Register left = locs()->in(0).reg(); | 614 Register left = locs()->in(0).reg(); |
| 648 Location right = locs()->in(1); | 615 Location right = locs()->in(1); |
| 649 if (right.IsConstant()) { | 616 if (right.IsConstant()) { |
| 650 ASSERT(right.constant().IsSmi()); | 617 ASSERT(right.constant().IsSmi()); |
| 651 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); | 618 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); |
| 652 __ testl(left, Immediate(imm)); | 619 __ testl(left, Immediate(imm)); |
| 653 } else { | 620 } else { |
| 654 __ testl(left, right.reg()); | 621 __ testl(left, right.reg()); |
| 655 } | 622 } |
| 656 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 623 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
| 657 return true_condition; | 624 return true_condition; |
| 658 } | 625 } |
| 659 | 626 |
| 660 | |
| 661 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 627 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
| 662 bool opt) const { | 628 bool opt) const { |
| 663 const intptr_t kNumInputs = 1; | 629 const intptr_t kNumInputs = 1; |
| 664 const intptr_t kNumTemps = 1; | 630 const intptr_t kNumTemps = 1; |
| 665 LocationSummary* locs = new (zone) | 631 LocationSummary* locs = new (zone) |
| 666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 632 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 667 locs->set_in(0, Location::RequiresRegister()); | 633 locs->set_in(0, Location::RequiresRegister()); |
| 668 locs->set_temp(0, Location::RequiresRegister()); | 634 locs->set_temp(0, Location::RequiresRegister()); |
| 669 locs->set_out(0, Location::RequiresRegister()); | 635 locs->set_out(0, Location::RequiresRegister()); |
| 670 return locs; | 636 return locs; |
| 671 } | 637 } |
| 672 | 638 |
| 673 | |
| 674 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 639 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 675 BranchLabels labels) { | 640 BranchLabels labels) { |
| 676 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 641 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
| 677 Register val_reg = locs()->in(0).reg(); | 642 Register val_reg = locs()->in(0).reg(); |
| 678 Register cid_reg = locs()->temp(0).reg(); | 643 Register cid_reg = locs()->temp(0).reg(); |
| 679 | 644 |
| 680 Label* deopt = | 645 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub( |
| 681 CanDeoptimize() | 646 deopt_id(), ICData::kDeoptTestCids, |
| 682 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, | 647 licm_hoisted_ ? ICData::kHoisted : 0) |
| 683 licm_hoisted_ ? ICData::kHoisted : 0) | 648 : NULL; |
| 684 : NULL; | |
| 685 | 649 |
| 686 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 650 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
| 687 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 651 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
| 688 ASSERT(data[0] == kSmiCid); | 652 ASSERT(data[0] == kSmiCid); |
| 689 bool result = data[1] == true_result; | 653 bool result = data[1] == true_result; |
| 690 __ testl(val_reg, Immediate(kSmiTagMask)); | 654 __ testl(val_reg, Immediate(kSmiTagMask)); |
| 691 __ j(ZERO, result ? labels.true_label : labels.false_label); | 655 __ j(ZERO, result ? labels.true_label : labels.false_label); |
| 692 __ LoadClassId(cid_reg, val_reg); | 656 __ LoadClassId(cid_reg, val_reg); |
| 693 for (intptr_t i = 2; i < data.length(); i += 2) { | 657 for (intptr_t i = 2; i < data.length(); i += 2) { |
| 694 const intptr_t test_cid = data[i]; | 658 const intptr_t test_cid = data[i]; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 707 __ jmp(target); | 671 __ jmp(target); |
| 708 } | 672 } |
| 709 } else { | 673 } else { |
| 710 __ jmp(deopt); | 674 __ jmp(deopt); |
| 711 } | 675 } |
| 712 // Dummy result as this method already did the jump, there's no need | 676 // Dummy result as this method already did the jump, there's no need |
| 713 // for the caller to branch on a condition. | 677 // for the caller to branch on a condition. |
| 714 return INVALID_CONDITION; | 678 return INVALID_CONDITION; |
| 715 } | 679 } |
| 716 | 680 |
| 717 | |
| 718 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 681 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
| 719 bool opt) const { | 682 bool opt) const { |
| 720 const intptr_t kNumInputs = 2; | 683 const intptr_t kNumInputs = 2; |
| 721 const intptr_t kNumTemps = 0; | 684 const intptr_t kNumTemps = 0; |
| 722 if (operation_cid() == kMintCid) { | 685 if (operation_cid() == kMintCid) { |
| 723 const intptr_t kNumTemps = 0; | 686 const intptr_t kNumTemps = 0; |
| 724 LocationSummary* locs = new (zone) | 687 LocationSummary* locs = new (zone) |
| 725 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 688 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 726 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 689 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 727 Location::RequiresRegister())); | 690 Location::RequiresRegister())); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 744 summary->set_in(0, Location::RegisterOrConstant(left())); | 707 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 745 // Only one input can be a constant operand. The case of two constant | 708 // Only one input can be a constant operand. The case of two constant |
| 746 // operands should be handled by constant propagation. | 709 // operands should be handled by constant propagation. |
| 747 summary->set_in(1, summary->in(0).IsConstant() | 710 summary->set_in(1, summary->in(0).IsConstant() |
| 748 ? Location::RequiresRegister() | 711 ? Location::RequiresRegister() |
| 749 : Location::RegisterOrConstant(right())); | 712 : Location::RegisterOrConstant(right())); |
| 750 summary->set_out(0, Location::RequiresRegister()); | 713 summary->set_out(0, Location::RequiresRegister()); |
| 751 return summary; | 714 return summary; |
| 752 } | 715 } |
| 753 | 716 |
| 754 | |
| 755 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 717 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 756 BranchLabels labels) { | 718 BranchLabels labels) { |
| 757 if (operation_cid() == kSmiCid) { | 719 if (operation_cid() == kSmiCid) { |
| 758 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 720 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 759 } else if (operation_cid() == kMintCid) { | 721 } else if (operation_cid() == kMintCid) { |
| 760 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); | 722 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); |
| 761 } else { | 723 } else { |
| 762 ASSERT(operation_cid() == kDoubleCid); | 724 ASSERT(operation_cid() == kDoubleCid); |
| 763 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 725 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 764 } | 726 } |
| 765 } | 727 } |
| 766 | 728 |
| 767 | |
| 768 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 729 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
| 769 bool opt) const { | 730 bool opt) const { |
| 770 return MakeCallSummary(zone); | 731 return MakeCallSummary(zone); |
| 771 } | 732 } |
| 772 | 733 |
| 773 | |
| 774 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 734 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 775 SetupNative(); | 735 SetupNative(); |
| 776 Register result = locs()->out(0).reg(); | 736 Register result = locs()->out(0).reg(); |
| 777 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 737 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
| 778 | 738 |
| 779 // Push the result place holder initialized to NULL. | 739 // Push the result place holder initialized to NULL. |
| 780 __ PushObject(Object::null_object()); | 740 __ PushObject(Object::null_object()); |
| 781 // Pass a pointer to the first argument in EAX. | 741 // Pass a pointer to the first argument in EAX. |
| 782 if (!function().HasOptionalParameters()) { | 742 if (!function().HasOptionalParameters()) { |
| 783 __ leal(EAX, | 743 __ leal(EAX, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 800 stub_entry = StubCode::CallNoScopeNative_entry(); | 760 stub_entry = StubCode::CallNoScopeNative_entry(); |
| 801 } | 761 } |
| 802 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); | 762 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); |
| 803 __ movl(ECX, Immediate(label.address())); | 763 __ movl(ECX, Immediate(label.address())); |
| 804 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, | 764 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
| 805 locs()); | 765 locs()); |
| 806 | 766 |
| 807 __ popl(result); | 767 __ popl(result); |
| 808 } | 768 } |
| 809 | 769 |
| 810 | |
| 811 static bool CanBeImmediateIndex(Value* value, intptr_t cid) { | 770 static bool CanBeImmediateIndex(Value* value, intptr_t cid) { |
| 812 ConstantInstr* constant = value->definition()->AsConstant(); | 771 ConstantInstr* constant = value->definition()->AsConstant(); |
| 813 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { | 772 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { |
| 814 return false; | 773 return false; |
| 815 } | 774 } |
| 816 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | 775 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |
| 817 const intptr_t scale = Instance::ElementSizeFor(cid); | 776 const intptr_t scale = Instance::ElementSizeFor(cid); |
| 818 const intptr_t offset = Instance::DataOffsetFor(cid); | 777 const intptr_t offset = Instance::DataOffsetFor(cid); |
| 819 const int64_t displacement = index * scale + offset; | 778 const int64_t displacement = index * scale + offset; |
| 820 return Utils::IsInt(32, displacement); | 779 return Utils::IsInt(32, displacement); |
| 821 } | 780 } |
| 822 | 781 |
| 823 | |
| 824 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 782 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
| 825 Zone* zone, | 783 Zone* zone, |
| 826 bool opt) const { | 784 bool opt) const { |
| 827 const intptr_t kNumInputs = 1; | 785 const intptr_t kNumInputs = 1; |
| 828 // TODO(fschneider): Allow immediate operands for the char code. | 786 // TODO(fschneider): Allow immediate operands for the char code. |
| 829 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 787 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 830 LocationSummary::kNoCall); | 788 LocationSummary::kNoCall); |
| 831 } | 789 } |
| 832 | 790 |
| 833 | |
| 834 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 791 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
| 835 FlowGraphCompiler* compiler) { | 792 FlowGraphCompiler* compiler) { |
| 836 Register char_code = locs()->in(0).reg(); | 793 Register char_code = locs()->in(0).reg(); |
| 837 Register result = locs()->out(0).reg(); | 794 Register result = locs()->out(0).reg(); |
| 838 __ movl(result, | 795 __ movl(result, |
| 839 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); | 796 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); |
| 840 __ movl(result, Address(result, char_code, | 797 __ movl(result, Address(result, char_code, |
| 841 TIMES_HALF_WORD_SIZE, // Char code is a smi. | 798 TIMES_HALF_WORD_SIZE, // Char code is a smi. |
| 842 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 799 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
| 843 } | 800 } |
| 844 | 801 |
| 845 | |
| 846 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 802 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
| 847 bool opt) const { | 803 bool opt) const { |
| 848 const intptr_t kNumInputs = 1; | 804 const intptr_t kNumInputs = 1; |
| 849 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 805 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 850 LocationSummary::kNoCall); | 806 LocationSummary::kNoCall); |
| 851 } | 807 } |
| 852 | 808 |
| 853 | |
| 854 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 809 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 855 ASSERT(cid_ == kOneByteStringCid); | 810 ASSERT(cid_ == kOneByteStringCid); |
| 856 Register str = locs()->in(0).reg(); | 811 Register str = locs()->in(0).reg(); |
| 857 Register result = locs()->out(0).reg(); | 812 Register result = locs()->out(0).reg(); |
| 858 Label is_one, done; | 813 Label is_one, done; |
| 859 __ movl(result, FieldAddress(str, String::length_offset())); | 814 __ movl(result, FieldAddress(str, String::length_offset())); |
| 860 __ cmpl(result, Immediate(Smi::RawValue(1))); | 815 __ cmpl(result, Immediate(Smi::RawValue(1))); |
| 861 __ j(EQUAL, &is_one, Assembler::kNearJump); | 816 __ j(EQUAL, &is_one, Assembler::kNearJump); |
| 862 __ movl(result, Immediate(Smi::RawValue(-1))); | 817 __ movl(result, Immediate(Smi::RawValue(-1))); |
| 863 __ jmp(&done); | 818 __ jmp(&done); |
| 864 __ Bind(&is_one); | 819 __ Bind(&is_one); |
| 865 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); | 820 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); |
| 866 __ SmiTag(result); | 821 __ SmiTag(result); |
| 867 __ Bind(&done); | 822 __ Bind(&done); |
| 868 } | 823 } |
| 869 | 824 |
| 870 | |
| 871 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 825 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
| 872 bool opt) const { | 826 bool opt) const { |
| 873 const intptr_t kNumInputs = 1; | 827 const intptr_t kNumInputs = 1; |
| 874 const intptr_t kNumTemps = 0; | 828 const intptr_t kNumTemps = 0; |
| 875 LocationSummary* summary = new (zone) | 829 LocationSummary* summary = new (zone) |
| 876 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 830 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 877 summary->set_in(0, Location::RegisterLocation(EAX)); | 831 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 878 summary->set_out(0, Location::RegisterLocation(EAX)); | 832 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 879 return summary; | 833 return summary; |
| 880 } | 834 } |
| 881 | 835 |
| 882 | |
| 883 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 836 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 884 Register array = locs()->in(0).reg(); | 837 Register array = locs()->in(0).reg(); |
| 885 __ pushl(array); | 838 __ pushl(array); |
| 886 const int kTypeArgsLen = 0; | 839 const int kTypeArgsLen = 0; |
| 887 const int kNumberOfArguments = 1; | 840 const int kNumberOfArguments = 1; |
| 888 const Array& kNoArgumentNames = Object::null_array(); | 841 const Array& kNoArgumentNames = Object::null_array(); |
| 889 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); | 842 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); |
| 890 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), | 843 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
| 891 args_info, locs(), ICData::Handle()); | 844 args_info, locs(), ICData::Handle()); |
| 892 ASSERT(locs()->out(0).reg() == EAX); | 845 ASSERT(locs()->out(0).reg() == EAX); |
| 893 } | 846 } |
| 894 | 847 |
| 895 | |
| 896 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 848 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
| 897 bool opt) const { | 849 bool opt) const { |
| 898 const intptr_t kNumInputs = 1; | 850 const intptr_t kNumInputs = 1; |
| 899 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), | 851 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
| 900 LocationSummary::kNoCall); | 852 LocationSummary::kNoCall); |
| 901 } | 853 } |
| 902 | 854 |
| 903 | |
| 904 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 855 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 905 Register obj = locs()->in(0).reg(); | 856 Register obj = locs()->in(0).reg(); |
| 906 Register result = locs()->out(0).reg(); | 857 Register result = locs()->out(0).reg(); |
| 907 if (object()->definition()->representation() == kUntagged) { | 858 if (object()->definition()->representation() == kUntagged) { |
| 908 __ movl(result, Address(obj, offset())); | 859 __ movl(result, Address(obj, offset())); |
| 909 } else { | 860 } else { |
| 910 ASSERT(object()->definition()->representation() == kTagged); | 861 ASSERT(object()->definition()->representation() == kTagged); |
| 911 __ movl(result, FieldAddress(obj, offset())); | 862 __ movl(result, FieldAddress(obj, offset())); |
| 912 } | 863 } |
| 913 } | 864 } |
| 914 | 865 |
| 915 | |
| 916 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 866 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
| 917 bool opt) const { | 867 bool opt) const { |
| 918 const intptr_t kNumInputs = 1; | 868 const intptr_t kNumInputs = 1; |
| 919 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 869 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 920 LocationSummary::kNoCall); | 870 LocationSummary::kNoCall); |
| 921 } | 871 } |
| 922 | 872 |
| 923 | |
| 924 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 873 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 925 const Register object = locs()->in(0).reg(); | 874 const Register object = locs()->in(0).reg(); |
| 926 const Register result = locs()->out(0).reg(); | 875 const Register result = locs()->out(0).reg(); |
| 927 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 876 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
| 928 if (CompileType::Smi().IsAssignableTo(value_type) || | 877 if (CompileType::Smi().IsAssignableTo(value_type) || |
| 929 value_type.IsTypeParameter()) { | 878 value_type.IsTypeParameter()) { |
| 930 // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses | 879 // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses |
| 931 // a conditional move instead, and requires an additional register---because | 880 // a conditional move instead, and requires an additional register---because |
| 932 // it is slower, probably due to branch prediction usually working just fine | 881 // it is slower, probably due to branch prediction usually working just fine |
| 933 // in this case. | 882 // in this case. |
| 934 ASSERT(result != object); | 883 ASSERT(result != object); |
| 935 Label done; | 884 Label done; |
| 936 __ movl(result, Immediate(kSmiCid << 1)); | 885 __ movl(result, Immediate(kSmiCid << 1)); |
| 937 __ testl(object, Immediate(kSmiTagMask)); | 886 __ testl(object, Immediate(kSmiTagMask)); |
| 938 __ j(EQUAL, &done, Assembler::kNearJump); | 887 __ j(EQUAL, &done, Assembler::kNearJump); |
| 939 __ LoadClassId(result, object); | 888 __ LoadClassId(result, object); |
| 940 __ SmiTag(result); | 889 __ SmiTag(result); |
| 941 __ Bind(&done); | 890 __ Bind(&done); |
| 942 } else { | 891 } else { |
| 943 __ LoadClassId(result, object); | 892 __ LoadClassId(result, object); |
| 944 __ SmiTag(result); | 893 __ SmiTag(result); |
| 945 } | 894 } |
| 946 } | 895 } |
| 947 | 896 |
| 948 | |
| 949 CompileType LoadIndexedInstr::ComputeType() const { | 897 CompileType LoadIndexedInstr::ComputeType() const { |
| 950 switch (class_id_) { | 898 switch (class_id_) { |
| 951 case kArrayCid: | 899 case kArrayCid: |
| 952 case kImmutableArrayCid: | 900 case kImmutableArrayCid: |
| 953 return CompileType::Dynamic(); | 901 return CompileType::Dynamic(); |
| 954 | 902 |
| 955 case kTypedDataFloat32ArrayCid: | 903 case kTypedDataFloat32ArrayCid: |
| 956 case kTypedDataFloat64ArrayCid: | 904 case kTypedDataFloat64ArrayCid: |
| 957 return CompileType::FromCid(kDoubleCid); | 905 return CompileType::FromCid(kDoubleCid); |
| 958 case kTypedDataFloat32x4ArrayCid: | 906 case kTypedDataFloat32x4ArrayCid: |
| (...skipping 19 matching lines...) Expand all Loading... |
| 978 case kTypedDataInt32ArrayCid: | 926 case kTypedDataInt32ArrayCid: |
| 979 case kTypedDataUint32ArrayCid: | 927 case kTypedDataUint32ArrayCid: |
| 980 return CompileType::Int(); | 928 return CompileType::Int(); |
| 981 | 929 |
| 982 default: | 930 default: |
| 983 UNIMPLEMENTED(); | 931 UNIMPLEMENTED(); |
| 984 return CompileType::Dynamic(); | 932 return CompileType::Dynamic(); |
| 985 } | 933 } |
| 986 } | 934 } |
| 987 | 935 |
| 988 | |
| 989 Representation LoadIndexedInstr::representation() const { | 936 Representation LoadIndexedInstr::representation() const { |
| 990 switch (class_id_) { | 937 switch (class_id_) { |
| 991 case kArrayCid: | 938 case kArrayCid: |
| 992 case kImmutableArrayCid: | 939 case kImmutableArrayCid: |
| 993 case kTypedDataInt8ArrayCid: | 940 case kTypedDataInt8ArrayCid: |
| 994 case kTypedDataUint8ArrayCid: | 941 case kTypedDataUint8ArrayCid: |
| 995 case kTypedDataUint8ClampedArrayCid: | 942 case kTypedDataUint8ClampedArrayCid: |
| 996 case kExternalTypedDataUint8ArrayCid: | 943 case kExternalTypedDataUint8ArrayCid: |
| 997 case kExternalTypedDataUint8ClampedArrayCid: | 944 case kExternalTypedDataUint8ClampedArrayCid: |
| 998 case kTypedDataInt16ArrayCid: | 945 case kTypedDataInt16ArrayCid: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1014 case kTypedDataInt32x4ArrayCid: | 961 case kTypedDataInt32x4ArrayCid: |
| 1015 return kUnboxedInt32x4; | 962 return kUnboxedInt32x4; |
| 1016 case kTypedDataFloat64x2ArrayCid: | 963 case kTypedDataFloat64x2ArrayCid: |
| 1017 return kUnboxedFloat64x2; | 964 return kUnboxedFloat64x2; |
| 1018 default: | 965 default: |
| 1019 UNIMPLEMENTED(); | 966 UNIMPLEMENTED(); |
| 1020 return kTagged; | 967 return kTagged; |
| 1021 } | 968 } |
| 1022 } | 969 } |
| 1023 | 970 |
| 1024 | |
| 1025 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 971 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1026 bool opt) const { | 972 bool opt) const { |
| 1027 const intptr_t kNumInputs = 2; | 973 const intptr_t kNumInputs = 2; |
| 1028 const intptr_t kNumTemps = 0; | 974 const intptr_t kNumTemps = 0; |
| 1029 LocationSummary* locs = new (zone) | 975 LocationSummary* locs = new (zone) |
| 1030 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 976 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1031 locs->set_in(0, Location::RequiresRegister()); | 977 locs->set_in(0, Location::RequiresRegister()); |
| 1032 if (CanBeImmediateIndex(index(), class_id())) { | 978 if (CanBeImmediateIndex(index(), class_id())) { |
| 1033 // CanBeImmediateIndex must return false for unsafe smis. | 979 // CanBeImmediateIndex must return false for unsafe smis. |
| 1034 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 980 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1049 } else if (representation() == kUnboxedInt32) { | 995 } else if (representation() == kUnboxedInt32) { |
| 1050 ASSERT(class_id() == kTypedDataInt32ArrayCid); | 996 ASSERT(class_id() == kTypedDataInt32ArrayCid); |
| 1051 locs->set_out(0, Location::RequiresRegister()); | 997 locs->set_out(0, Location::RequiresRegister()); |
| 1052 } else { | 998 } else { |
| 1053 ASSERT(representation() == kTagged); | 999 ASSERT(representation() == kTagged); |
| 1054 locs->set_out(0, Location::RequiresRegister()); | 1000 locs->set_out(0, Location::RequiresRegister()); |
| 1055 } | 1001 } |
| 1056 return locs; | 1002 return locs; |
| 1057 } | 1003 } |
| 1058 | 1004 |
| 1059 | |
| 1060 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1005 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1061 // The array register points to the backing store for external arrays. | 1006 // The array register points to the backing store for external arrays. |
| 1062 const Register array = locs()->in(0).reg(); | 1007 const Register array = locs()->in(0).reg(); |
| 1063 const Location index = locs()->in(1); | 1008 const Location index = locs()->in(1); |
| 1064 | 1009 |
| 1065 Address element_address = | 1010 Address element_address = |
| 1066 index.IsRegister() | 1011 index.IsRegister() |
| 1067 ? Assembler::ElementAddressForRegIndex( | 1012 ? Assembler::ElementAddressForRegIndex( |
| 1068 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1013 IsExternal(), class_id(), index_scale(), array, index.reg()) |
| 1069 : Assembler::ElementAddressForIntIndex( | 1014 : Assembler::ElementAddressForIntIndex( |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1149 __ movzxw(result, element_address); | 1094 __ movzxw(result, element_address); |
| 1150 __ SmiTag(result); | 1095 __ SmiTag(result); |
| 1151 break; | 1096 break; |
| 1152 default: | 1097 default: |
| 1153 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1098 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1154 __ movl(result, element_address); | 1099 __ movl(result, element_address); |
| 1155 break; | 1100 break; |
| 1156 } | 1101 } |
| 1157 } | 1102 } |
| 1158 | 1103 |
| 1159 | |
| 1160 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1104 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1161 intptr_t idx) const { | 1105 intptr_t idx) const { |
| 1162 // Array can be a Dart object or a pointer to external data. | 1106 // Array can be a Dart object or a pointer to external data. |
| 1163 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1107 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
| 1164 if (idx == 1) return kTagged; // Index is a smi. | 1108 if (idx == 1) return kTagged; // Index is a smi. |
| 1165 ASSERT(idx == 2); | 1109 ASSERT(idx == 2); |
| 1166 switch (class_id_) { | 1110 switch (class_id_) { |
| 1167 case kArrayCid: | 1111 case kArrayCid: |
| 1168 case kOneByteStringCid: | 1112 case kOneByteStringCid: |
| 1169 case kTypedDataInt8ArrayCid: | 1113 case kTypedDataInt8ArrayCid: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1186 case kTypedDataInt32x4ArrayCid: | 1130 case kTypedDataInt32x4ArrayCid: |
| 1187 return kUnboxedInt32x4; | 1131 return kUnboxedInt32x4; |
| 1188 case kTypedDataFloat64x2ArrayCid: | 1132 case kTypedDataFloat64x2ArrayCid: |
| 1189 return kUnboxedFloat64x2; | 1133 return kUnboxedFloat64x2; |
| 1190 default: | 1134 default: |
| 1191 UNIMPLEMENTED(); | 1135 UNIMPLEMENTED(); |
| 1192 return kTagged; | 1136 return kTagged; |
| 1193 } | 1137 } |
| 1194 } | 1138 } |
| 1195 | 1139 |
| 1196 | |
| 1197 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1140 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1198 bool opt) const { | 1141 bool opt) const { |
| 1199 const intptr_t kNumInputs = 3; | 1142 const intptr_t kNumInputs = 3; |
| 1200 const intptr_t kNumTemps = 0; | 1143 const intptr_t kNumTemps = 0; |
| 1201 LocationSummary* locs = new (zone) | 1144 LocationSummary* locs = new (zone) |
| 1202 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1145 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1203 locs->set_in(0, Location::RequiresRegister()); | 1146 locs->set_in(0, Location::RequiresRegister()); |
| 1204 if (CanBeImmediateIndex(index(), class_id())) { | 1147 if (CanBeImmediateIndex(index(), class_id())) { |
| 1205 // CanBeImmediateIndex must return false for unsafe smis. | 1148 // CanBeImmediateIndex must return false for unsafe smis. |
| 1206 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1149 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1245 case kTypedDataFloat64x2ArrayCid: | 1188 case kTypedDataFloat64x2ArrayCid: |
| 1246 locs->set_in(2, Location::RequiresFpuRegister()); | 1189 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1247 break; | 1190 break; |
| 1248 default: | 1191 default: |
| 1249 UNREACHABLE(); | 1192 UNREACHABLE(); |
| 1250 return NULL; | 1193 return NULL; |
| 1251 } | 1194 } |
| 1252 return locs; | 1195 return locs; |
| 1253 } | 1196 } |
| 1254 | 1197 |
| 1255 | |
| 1256 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1198 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1257 // The array register points to the backing store for external arrays. | 1199 // The array register points to the backing store for external arrays. |
| 1258 const Register array = locs()->in(0).reg(); | 1200 const Register array = locs()->in(0).reg(); |
| 1259 const Location index = locs()->in(1); | 1201 const Location index = locs()->in(1); |
| 1260 | 1202 |
| 1261 Address element_address = | 1203 Address element_address = |
| 1262 index.IsRegister() | 1204 index.IsRegister() |
| 1263 ? Assembler::ElementAddressForRegIndex( | 1205 ? Assembler::ElementAddressForRegIndex( |
| 1264 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1206 IsExternal(), class_id(), index_scale(), array, index.reg()) |
| 1265 : Assembler::ElementAddressForIntIndex( | 1207 : Assembler::ElementAddressForIntIndex( |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1345 case kTypedDataInt32x4ArrayCid: | 1287 case kTypedDataInt32x4ArrayCid: |
| 1346 case kTypedDataFloat32x4ArrayCid: | 1288 case kTypedDataFloat32x4ArrayCid: |
| 1347 case kTypedDataFloat64x2ArrayCid: | 1289 case kTypedDataFloat64x2ArrayCid: |
| 1348 __ movups(element_address, locs()->in(2).fpu_reg()); | 1290 __ movups(element_address, locs()->in(2).fpu_reg()); |
| 1349 break; | 1291 break; |
| 1350 default: | 1292 default: |
| 1351 UNREACHABLE(); | 1293 UNREACHABLE(); |
| 1352 } | 1294 } |
| 1353 } | 1295 } |
| 1354 | 1296 |
| 1355 | |
| 1356 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1297 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
| 1357 bool opt) const { | 1298 bool opt) const { |
| 1358 const intptr_t kNumInputs = 1; | 1299 const intptr_t kNumInputs = 1; |
| 1359 | 1300 |
| 1360 const intptr_t value_cid = value()->Type()->ToCid(); | 1301 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1361 const intptr_t field_cid = field().guarded_cid(); | 1302 const intptr_t field_cid = field().guarded_cid(); |
| 1362 | 1303 |
| 1363 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 1304 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
| 1364 const bool needs_value_cid_temp_reg = | 1305 const bool needs_value_cid_temp_reg = |
| 1365 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1306 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1377 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1318 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1378 summary->set_in(0, Location::RequiresRegister()); | 1319 summary->set_in(0, Location::RequiresRegister()); |
| 1379 | 1320 |
| 1380 for (intptr_t i = 0; i < num_temps; i++) { | 1321 for (intptr_t i = 0; i < num_temps; i++) { |
| 1381 summary->set_temp(i, Location::RequiresRegister()); | 1322 summary->set_temp(i, Location::RequiresRegister()); |
| 1382 } | 1323 } |
| 1383 | 1324 |
| 1384 return summary; | 1325 return summary; |
| 1385 } | 1326 } |
| 1386 | 1327 |
| 1387 | |
| 1388 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1328 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1389 ASSERT(sizeof(classid_t) == kInt16Size); | 1329 ASSERT(sizeof(classid_t) == kInt16Size); |
| 1390 const intptr_t value_cid = value()->Type()->ToCid(); | 1330 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1391 const intptr_t field_cid = field().guarded_cid(); | 1331 const intptr_t field_cid = field().guarded_cid(); |
| 1392 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1332 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 1393 | 1333 |
| 1394 if (field_cid == kDynamicCid) { | 1334 if (field_cid == kDynamicCid) { |
| 1395 if (Compiler::IsBackgroundCompilation()) { | 1335 if (Compiler::IsBackgroundCompilation()) { |
| 1396 // Field state changed while compiling. | 1336 // Field state changed while compiling. |
| 1397 Compiler::AbortBackgroundCompilation( | 1337 Compiler::AbortBackgroundCompilation( |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 __ j(NOT_EQUAL, fail); | 1463 __ j(NOT_EQUAL, fail); |
| 1524 } else { | 1464 } else { |
| 1525 // Both value's and field's class id is known. | 1465 // Both value's and field's class id is known. |
| 1526 ASSERT((value_cid != field_cid) && (value_cid != nullability)); | 1466 ASSERT((value_cid != field_cid) && (value_cid != nullability)); |
| 1527 __ jmp(fail); | 1467 __ jmp(fail); |
| 1528 } | 1468 } |
| 1529 } | 1469 } |
| 1530 __ Bind(&ok); | 1470 __ Bind(&ok); |
| 1531 } | 1471 } |
| 1532 | 1472 |
| 1533 | |
| 1534 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1473 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
| 1535 bool opt) const { | 1474 bool opt) const { |
| 1536 const intptr_t kNumInputs = 1; | 1475 const intptr_t kNumInputs = 1; |
| 1537 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1476 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1538 const intptr_t kNumTemps = 3; | 1477 const intptr_t kNumTemps = 3; |
| 1539 LocationSummary* summary = new (zone) | 1478 LocationSummary* summary = new (zone) |
| 1540 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1479 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1541 summary->set_in(0, Location::RequiresRegister()); | 1480 summary->set_in(0, Location::RequiresRegister()); |
| 1542 // We need temporaries for field object, length offset and expected length. | 1481 // We need temporaries for field object, length offset and expected length. |
| 1543 summary->set_temp(0, Location::RequiresRegister()); | 1482 summary->set_temp(0, Location::RequiresRegister()); |
| 1544 summary->set_temp(1, Location::RequiresRegister()); | 1483 summary->set_temp(1, Location::RequiresRegister()); |
| 1545 summary->set_temp(2, Location::RequiresRegister()); | 1484 summary->set_temp(2, Location::RequiresRegister()); |
| 1546 return summary; | 1485 return summary; |
| 1547 } else { | 1486 } else { |
| 1548 LocationSummary* summary = new (zone) | 1487 LocationSummary* summary = new (zone) |
| 1549 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 1488 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 1550 summary->set_in(0, Location::RequiresRegister()); | 1489 summary->set_in(0, Location::RequiresRegister()); |
| 1551 return summary; | 1490 return summary; |
| 1552 } | 1491 } |
| 1553 UNREACHABLE(); | 1492 UNREACHABLE(); |
| 1554 } | 1493 } |
| 1555 | 1494 |
| 1556 | |
| 1557 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1495 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1558 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1496 if (field().guarded_list_length() == Field::kNoFixedLength) { |
| 1559 if (Compiler::IsBackgroundCompilation()) { | 1497 if (Compiler::IsBackgroundCompilation()) { |
| 1560 // Field state changed while compiling. | 1498 // Field state changed while compiling. |
| 1561 Compiler::AbortBackgroundCompilation( | 1499 Compiler::AbortBackgroundCompilation( |
| 1562 deopt_id(), | 1500 deopt_id(), |
| 1563 "GuardFieldLengthInstr: field state changed while compiling"); | 1501 "GuardFieldLengthInstr: field state changed while compiling"); |
| 1564 } | 1502 } |
| 1565 ASSERT(!compiler->is_optimizing()); | 1503 ASSERT(!compiler->is_optimizing()); |
| 1566 return; // Nothing to emit. | 1504 return; // Nothing to emit. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1617 ASSERT(field().guarded_list_length_in_object_offset() != | 1555 ASSERT(field().guarded_list_length_in_object_offset() != |
| 1618 Field::kUnknownLengthOffset); | 1556 Field::kUnknownLengthOffset); |
| 1619 | 1557 |
| 1620 __ cmpl( | 1558 __ cmpl( |
| 1621 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), | 1559 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), |
| 1622 Immediate(Smi::RawValue(field().guarded_list_length()))); | 1560 Immediate(Smi::RawValue(field().guarded_list_length()))); |
| 1623 __ j(NOT_EQUAL, deopt); | 1561 __ j(NOT_EQUAL, deopt); |
| 1624 } | 1562 } |
| 1625 } | 1563 } |
| 1626 | 1564 |
| 1627 | |
| 1628 class BoxAllocationSlowPath : public SlowPathCode { | 1565 class BoxAllocationSlowPath : public SlowPathCode { |
| 1629 public: | 1566 public: |
| 1630 BoxAllocationSlowPath(Instruction* instruction, | 1567 BoxAllocationSlowPath(Instruction* instruction, |
| 1631 const Class& cls, | 1568 const Class& cls, |
| 1632 Register result) | 1569 Register result) |
| 1633 : instruction_(instruction), cls_(cls), result_(result) {} | 1570 : instruction_(instruction), cls_(cls), result_(result) {} |
| 1634 | 1571 |
| 1635 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1572 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1636 if (Assembler::EmittingComments()) { | 1573 if (Assembler::EmittingComments()) { |
| 1637 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), | 1574 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1673 __ Bind(slow_path->exit_label()); | 1610 __ Bind(slow_path->exit_label()); |
| 1674 } | 1611 } |
| 1675 } | 1612 } |
| 1676 | 1613 |
| 1677 private: | 1614 private: |
| 1678 Instruction* instruction_; | 1615 Instruction* instruction_; |
| 1679 const Class& cls_; | 1616 const Class& cls_; |
| 1680 const Register result_; | 1617 const Register result_; |
| 1681 }; | 1618 }; |
| 1682 | 1619 |
| 1683 | |
| 1684 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 1620 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
| 1685 bool opt) const { | 1621 bool opt) const { |
| 1686 const intptr_t kNumInputs = 2; | 1622 const intptr_t kNumInputs = 2; |
| 1687 const intptr_t kNumTemps = | 1623 const intptr_t kNumTemps = |
| 1688 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); | 1624 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
| 1689 LocationSummary* summary = new (zone) | 1625 LocationSummary* summary = new (zone) |
| 1690 LocationSummary(zone, kNumInputs, kNumTemps, | 1626 LocationSummary(zone, kNumInputs, kNumTemps, |
| 1691 ((IsUnboxedStore() && opt && is_initialization()) || | 1627 ((IsUnboxedStore() && opt && is_initialization()) || |
| 1692 IsPotentialUnboxedStore()) | 1628 IsPotentialUnboxedStore()) |
| 1693 ? LocationSummary::kCallOnSlowPath | 1629 ? LocationSummary::kCallOnSlowPath |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1706 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 1642 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
| 1707 : Location::FpuRegisterLocation(XMM1)); | 1643 : Location::FpuRegisterLocation(XMM1)); |
| 1708 } else { | 1644 } else { |
| 1709 summary->set_in(1, ShouldEmitStoreBarrier() | 1645 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1710 ? Location::WritableRegister() | 1646 ? Location::WritableRegister() |
| 1711 : Location::RegisterOrConstant(value())); | 1647 : Location::RegisterOrConstant(value())); |
| 1712 } | 1648 } |
| 1713 return summary; | 1649 return summary; |
| 1714 } | 1650 } |
| 1715 | 1651 |
| 1716 | |
| 1717 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 1652 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
| 1718 StoreInstanceFieldInstr* instruction, | 1653 StoreInstanceFieldInstr* instruction, |
| 1719 Register box_reg, | 1654 Register box_reg, |
| 1720 const Class& cls, | 1655 const Class& cls, |
| 1721 Register instance_reg, | 1656 Register instance_reg, |
| 1722 intptr_t offset, | 1657 intptr_t offset, |
| 1723 Register temp) { | 1658 Register temp) { |
| 1724 Label done; | 1659 Label done; |
| 1725 const Immediate& raw_null = | 1660 const Immediate& raw_null = |
| 1726 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1661 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1727 __ movl(box_reg, FieldAddress(instance_reg, offset)); | 1662 __ movl(box_reg, FieldAddress(instance_reg, offset)); |
| 1728 __ cmpl(box_reg, raw_null); | 1663 __ cmpl(box_reg, raw_null); |
| 1729 __ j(NOT_EQUAL, &done); | 1664 __ j(NOT_EQUAL, &done); |
| 1730 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); | 1665 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
| 1731 __ movl(temp, box_reg); | 1666 __ movl(temp, box_reg); |
| 1732 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); | 1667 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); |
| 1733 | 1668 |
| 1734 __ Bind(&done); | 1669 __ Bind(&done); |
| 1735 } | 1670 } |
| 1736 | 1671 |
| 1737 | |
| 1738 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1672 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1739 ASSERT(sizeof(classid_t) == kInt16Size); | 1673 ASSERT(sizeof(classid_t) == kInt16Size); |
| 1740 Label skip_store; | 1674 Label skip_store; |
| 1741 | 1675 |
| 1742 Register instance_reg = locs()->in(0).reg(); | 1676 Register instance_reg = locs()->in(0).reg(); |
| 1743 | 1677 |
| 1744 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1678 if (IsUnboxedStore() && compiler->is_optimizing()) { |
| 1745 XmmRegister value = locs()->in(1).fpu_reg(); | 1679 XmmRegister value = locs()->in(1).fpu_reg(); |
| 1746 Register temp = locs()->temp(0).reg(); | 1680 Register temp = locs()->temp(0).reg(); |
| 1747 Register temp2 = locs()->temp(1).reg(); | 1681 Register temp2 = locs()->temp(1).reg(); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1825 Immediate(kFloat32x4Cid)); | 1759 Immediate(kFloat32x4Cid)); |
| 1826 __ j(EQUAL, &store_float32x4); | 1760 __ j(EQUAL, &store_float32x4); |
| 1827 | 1761 |
| 1828 __ cmpw(FieldAddress(temp, Field::guarded_cid_offset()), | 1762 __ cmpw(FieldAddress(temp, Field::guarded_cid_offset()), |
| 1829 Immediate(kFloat64x2Cid)); | 1763 Immediate(kFloat64x2Cid)); |
| 1830 __ j(EQUAL, &store_float64x2); | 1764 __ j(EQUAL, &store_float64x2); |
| 1831 | 1765 |
| 1832 // Fall through. | 1766 // Fall through. |
| 1833 __ jmp(&store_pointer); | 1767 __ jmp(&store_pointer); |
| 1834 | 1768 |
| 1835 | |
| 1836 if (!compiler->is_optimizing()) { | 1769 if (!compiler->is_optimizing()) { |
| 1837 locs()->live_registers()->Add(locs()->in(0)); | 1770 locs()->live_registers()->Add(locs()->in(0)); |
| 1838 locs()->live_registers()->Add(locs()->in(1)); | 1771 locs()->live_registers()->Add(locs()->in(1)); |
| 1839 } | 1772 } |
| 1840 | 1773 |
| 1841 { | 1774 { |
| 1842 __ Bind(&store_double); | 1775 __ Bind(&store_double); |
| 1843 EnsureMutableBox(compiler, this, temp, compiler->double_class(), | 1776 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
| 1844 instance_reg, offset_in_bytes_, temp2); | 1777 instance_reg, offset_in_bytes_, temp2); |
| 1845 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); | 1778 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1881 } else { | 1814 } else { |
| 1882 Register value_reg = locs()->in(1).reg(); | 1815 Register value_reg = locs()->in(1).reg(); |
| 1883 __ StoreIntoObjectNoBarrier(instance_reg, | 1816 __ StoreIntoObjectNoBarrier(instance_reg, |
| 1884 FieldAddress(instance_reg, offset_in_bytes_), | 1817 FieldAddress(instance_reg, offset_in_bytes_), |
| 1885 value_reg); | 1818 value_reg); |
| 1886 } | 1819 } |
| 1887 } | 1820 } |
| 1888 __ Bind(&skip_store); | 1821 __ Bind(&skip_store); |
| 1889 } | 1822 } |
| 1890 | 1823 |
| 1891 | |
| 1892 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1824 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 1893 bool opt) const { | 1825 bool opt) const { |
| 1894 const intptr_t kNumInputs = 1; | 1826 const intptr_t kNumInputs = 1; |
| 1895 const intptr_t kNumTemps = 0; | 1827 const intptr_t kNumTemps = 0; |
| 1896 LocationSummary* summary = new (zone) | 1828 LocationSummary* summary = new (zone) |
| 1897 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1829 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1898 summary->set_in(0, Location::RequiresRegister()); | 1830 summary->set_in(0, Location::RequiresRegister()); |
| 1899 // By specifying same register as input, our simple register allocator can | 1831 // By specifying same register as input, our simple register allocator can |
| 1900 // generate better code. | 1832 // generate better code. |
| 1901 summary->set_out(0, Location::SameAsFirstInput()); | 1833 summary->set_out(0, Location::SameAsFirstInput()); |
| 1902 return summary; | 1834 return summary; |
| 1903 } | 1835 } |
| 1904 | 1836 |
| 1905 | |
| 1906 // When the parser is building an implicit static getter for optimization, | 1837 // When the parser is building an implicit static getter for optimization, |
| 1907 // it can generate a function body where deoptimization ids do not line up | 1838 // it can generate a function body where deoptimization ids do not line up |
| 1908 // with the unoptimized code. | 1839 // with the unoptimized code. |
| 1909 // | 1840 // |
| 1910 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 1841 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 1911 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1842 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1912 Register field = locs()->in(0).reg(); | 1843 Register field = locs()->in(0).reg(); |
| 1913 Register result = locs()->out(0).reg(); | 1844 Register result = locs()->out(0).reg(); |
| 1914 __ movl(result, FieldAddress(field, Field::static_value_offset())); | 1845 __ movl(result, FieldAddress(field, Field::static_value_offset())); |
| 1915 } | 1846 } |
| 1916 | 1847 |
| 1917 | |
| 1918 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1848 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 1919 bool opt) const { | 1849 bool opt) const { |
| 1920 LocationSummary* locs = | 1850 LocationSummary* locs = |
| 1921 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); | 1851 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
| 1922 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 1852 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 1923 : Location::RequiresRegister()); | 1853 : Location::RequiresRegister()); |
| 1924 locs->set_temp(0, Location::RequiresRegister()); | 1854 locs->set_temp(0, Location::RequiresRegister()); |
| 1925 return locs; | 1855 return locs; |
| 1926 } | 1856 } |
| 1927 | 1857 |
| 1928 | |
| 1929 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1858 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1930 Register value = locs()->in(0).reg(); | 1859 Register value = locs()->in(0).reg(); |
| 1931 Register temp = locs()->temp(0).reg(); | 1860 Register temp = locs()->temp(0).reg(); |
| 1932 | 1861 |
| 1933 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 1862 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
| 1934 if (this->value()->NeedsStoreBuffer()) { | 1863 if (this->value()->NeedsStoreBuffer()) { |
| 1935 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), | 1864 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
| 1936 value, CanValueBeSmi()); | 1865 value, CanValueBeSmi()); |
| 1937 } else { | 1866 } else { |
| 1938 __ StoreIntoObjectNoBarrier( | 1867 __ StoreIntoObjectNoBarrier( |
| 1939 temp, FieldAddress(temp, Field::static_value_offset()), value); | 1868 temp, FieldAddress(temp, Field::static_value_offset()), value); |
| 1940 } | 1869 } |
| 1941 } | 1870 } |
| 1942 | 1871 |
| 1943 | |
| 1944 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 1872 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
| 1945 bool opt) const { | 1873 bool opt) const { |
| 1946 const intptr_t kNumInputs = 3; | 1874 const intptr_t kNumInputs = 3; |
| 1947 const intptr_t kNumTemps = 0; | 1875 const intptr_t kNumTemps = 0; |
| 1948 LocationSummary* summary = new (zone) | 1876 LocationSummary* summary = new (zone) |
| 1949 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1877 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1950 summary->set_in(0, Location::RegisterLocation(EAX)); // Instance. | 1878 summary->set_in(0, Location::RegisterLocation(EAX)); // Instance. |
| 1951 summary->set_in(1, Location::RegisterLocation(EDX)); // Instant. type args. | 1879 summary->set_in(1, Location::RegisterLocation(EDX)); // Instant. type args. |
| 1952 summary->set_in(2, Location::RegisterLocation(ECX)); // Function type args. | 1880 summary->set_in(2, Location::RegisterLocation(ECX)); // Function type args. |
| 1953 summary->set_out(0, Location::RegisterLocation(EAX)); | 1881 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 1954 return summary; | 1882 return summary; |
| 1955 } | 1883 } |
| 1956 | 1884 |
| 1957 | |
| 1958 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1885 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1959 ASSERT(locs()->in(0).reg() == EAX); // Value. | 1886 ASSERT(locs()->in(0).reg() == EAX); // Value. |
| 1960 ASSERT(locs()->in(1).reg() == EDX); // Instantiator type arguments. | 1887 ASSERT(locs()->in(1).reg() == EDX); // Instantiator type arguments. |
| 1961 ASSERT(locs()->in(2).reg() == ECX); // Function type arguments. | 1888 ASSERT(locs()->in(2).reg() == ECX); // Function type arguments. |
| 1962 | 1889 |
| 1963 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); | 1890 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); |
| 1964 ASSERT(locs()->out(0).reg() == EAX); | 1891 ASSERT(locs()->out(0).reg() == EAX); |
| 1965 } | 1892 } |
| 1966 | 1893 |
| 1967 | |
| 1968 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and | 1894 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and |
| 1969 // use slow path stub. | 1895 // use slow path stub. |
| 1970 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 1896 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
| 1971 bool opt) const { | 1897 bool opt) const { |
| 1972 const intptr_t kNumInputs = 2; | 1898 const intptr_t kNumInputs = 2; |
| 1973 const intptr_t kNumTemps = 0; | 1899 const intptr_t kNumTemps = 0; |
| 1974 LocationSummary* locs = new (zone) | 1900 LocationSummary* locs = new (zone) |
| 1975 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1901 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1976 locs->set_in(0, Location::RegisterLocation(ECX)); | 1902 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 1977 locs->set_in(1, Location::RegisterLocation(EDX)); | 1903 locs->set_in(1, Location::RegisterLocation(EDX)); |
| 1978 locs->set_out(0, Location::RegisterLocation(EAX)); | 1904 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 1979 return locs; | 1905 return locs; |
| 1980 } | 1906 } |
| 1981 | 1907 |
| 1982 | |
| 1983 // Inlines array allocation for known constant values. | 1908 // Inlines array allocation for known constant values. |
| 1984 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 1909 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
| 1985 intptr_t num_elements, | 1910 intptr_t num_elements, |
| 1986 Label* slow_path, | 1911 Label* slow_path, |
| 1987 Label* done) { | 1912 Label* done) { |
| 1988 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 1913 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
| 1989 const Register kLengthReg = EDX; | 1914 const Register kLengthReg = EDX; |
| 1990 const Register kElemTypeReg = ECX; | 1915 const Register kElemTypeReg = ECX; |
| 1991 const intptr_t instance_size = Array::InstanceSize(num_elements); | 1916 const intptr_t instance_size = Array::InstanceSize(num_elements); |
| 1992 | 1917 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2027 __ Bind(&init_loop); | 1952 __ Bind(&init_loop); |
| 2028 __ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), Object::null_object()); | 1953 __ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), Object::null_object()); |
| 2029 __ addl(EDI, Immediate(kWordSize)); | 1954 __ addl(EDI, Immediate(kWordSize)); |
| 2030 __ cmpl(EDI, EBX); | 1955 __ cmpl(EDI, EBX); |
| 2031 __ j(BELOW, &init_loop, Assembler::kNearJump); | 1956 __ j(BELOW, &init_loop, Assembler::kNearJump); |
| 2032 } | 1957 } |
| 2033 } | 1958 } |
| 2034 __ jmp(done, Assembler::kNearJump); | 1959 __ jmp(done, Assembler::kNearJump); |
| 2035 } | 1960 } |
| 2036 | 1961 |
| 2037 | |
| 2038 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1962 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2039 // Allocate the array. EDX = length, ECX = element type. | 1963 // Allocate the array. EDX = length, ECX = element type. |
| 2040 const Register kLengthReg = EDX; | 1964 const Register kLengthReg = EDX; |
| 2041 const Register kElemTypeReg = ECX; | 1965 const Register kElemTypeReg = ECX; |
| 2042 const Register kResultReg = EAX; | 1966 const Register kResultReg = EAX; |
| 2043 ASSERT(locs()->in(0).reg() == kElemTypeReg); | 1967 ASSERT(locs()->in(0).reg() == kElemTypeReg); |
| 2044 ASSERT(locs()->in(1).reg() == kLengthReg); | 1968 ASSERT(locs()->in(1).reg() == kLengthReg); |
| 2045 | 1969 |
| 2046 Label slow_path, done; | 1970 Label slow_path, done; |
| 2047 if (compiler->is_optimizing() && num_elements()->BindsToConstant() && | 1971 if (compiler->is_optimizing() && num_elements()->BindsToConstant() && |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2067 const Code& stub = Code::ZoneHandle(compiler->zone(), | 1991 const Code& stub = Code::ZoneHandle(compiler->zone(), |
| 2068 StubCode::AllocateArray_entry()->code()); | 1992 StubCode::AllocateArray_entry()->code()); |
| 2069 compiler->AddStubCallTarget(stub); | 1993 compiler->AddStubCallTarget(stub); |
| 2070 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), | 1994 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), |
| 2071 *StubCode::AllocateArray_entry(), | 1995 *StubCode::AllocateArray_entry(), |
| 2072 RawPcDescriptors::kOther, locs()); | 1996 RawPcDescriptors::kOther, locs()); |
| 2073 __ Bind(&done); | 1997 __ Bind(&done); |
| 2074 ASSERT(locs()->out(0).reg() == kResultReg); | 1998 ASSERT(locs()->out(0).reg() == kResultReg); |
| 2075 } | 1999 } |
| 2076 | 2000 |
| 2077 | |
| 2078 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2001 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
| 2079 bool opt) const { | 2002 bool opt) const { |
| 2080 const intptr_t kNumInputs = 1; | 2003 const intptr_t kNumInputs = 1; |
| 2081 const intptr_t kNumTemps = | 2004 const intptr_t kNumTemps = |
| 2082 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); | 2005 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); |
| 2083 | 2006 |
| 2084 LocationSummary* locs = new (zone) LocationSummary( | 2007 LocationSummary* locs = new (zone) LocationSummary( |
| 2085 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) | 2008 zone, kNumInputs, kNumTemps, |
| 2086 ? LocationSummary::kNoCall | 2009 (opt && !IsPotentialUnboxedLoad()) ? LocationSummary::kNoCall |
| 2087 : LocationSummary::kCallOnSlowPath); | 2010 : LocationSummary::kCallOnSlowPath); |
| 2088 | 2011 |
| 2089 locs->set_in(0, Location::RequiresRegister()); | 2012 locs->set_in(0, Location::RequiresRegister()); |
| 2090 | 2013 |
| 2091 if (IsUnboxedLoad() && opt) { | 2014 if (IsUnboxedLoad() && opt) { |
| 2092 locs->set_temp(0, Location::RequiresRegister()); | 2015 locs->set_temp(0, Location::RequiresRegister()); |
| 2093 } else if (IsPotentialUnboxedLoad()) { | 2016 } else if (IsPotentialUnboxedLoad()) { |
| 2094 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2017 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
| 2095 : Location::FpuRegisterLocation(XMM1)); | 2018 : Location::FpuRegisterLocation(XMM1)); |
| 2096 locs->set_temp(1, Location::RequiresRegister()); | 2019 locs->set_temp(1, Location::RequiresRegister()); |
| 2097 } | 2020 } |
| 2098 locs->set_out(0, Location::RequiresRegister()); | 2021 locs->set_out(0, Location::RequiresRegister()); |
| 2099 return locs; | 2022 return locs; |
| 2100 } | 2023 } |
| 2101 | 2024 |
| 2102 | |
| 2103 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2025 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2104 ASSERT(sizeof(classid_t) == kInt16Size); | 2026 ASSERT(sizeof(classid_t) == kInt16Size); |
| 2105 | 2027 |
| 2106 Register instance_reg = locs()->in(0).reg(); | 2028 Register instance_reg = locs()->in(0).reg(); |
| 2107 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2029 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
| 2108 XmmRegister result = locs()->out(0).fpu_reg(); | 2030 XmmRegister result = locs()->out(0).fpu_reg(); |
| 2109 Register temp = locs()->temp(0).reg(); | 2031 Register temp = locs()->temp(0).reg(); |
| 2110 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2032 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2111 const intptr_t cid = field()->UnboxedFieldCid(); | 2033 const intptr_t cid = field()->UnboxedFieldCid(); |
| 2112 switch (cid) { | 2034 switch (cid) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2127 } | 2049 } |
| 2128 return; | 2050 return; |
| 2129 } | 2051 } |
| 2130 | 2052 |
| 2131 Label done; | 2053 Label done; |
| 2132 Register result = locs()->out(0).reg(); | 2054 Register result = locs()->out(0).reg(); |
| 2133 if (IsPotentialUnboxedLoad()) { | 2055 if (IsPotentialUnboxedLoad()) { |
| 2134 Register temp = locs()->temp(1).reg(); | 2056 Register temp = locs()->temp(1).reg(); |
| 2135 XmmRegister value = locs()->temp(0).fpu_reg(); | 2057 XmmRegister value = locs()->temp(0).fpu_reg(); |
| 2136 | 2058 |
| 2137 | |
| 2138 Label load_pointer; | 2059 Label load_pointer; |
| 2139 Label load_double; | 2060 Label load_double; |
| 2140 Label load_float32x4; | 2061 Label load_float32x4; |
| 2141 Label load_float64x2; | 2062 Label load_float64x2; |
| 2142 | 2063 |
| 2143 __ LoadObject(result, Field::ZoneHandle(field()->Original())); | 2064 __ LoadObject(result, Field::ZoneHandle(field()->Original())); |
| 2144 | 2065 |
| 2145 FieldAddress field_cid_operand(result, Field::guarded_cid_offset()); | 2066 FieldAddress field_cid_operand(result, Field::guarded_cid_offset()); |
| 2146 FieldAddress field_nullability_operand(result, Field::is_nullable_offset()); | 2067 FieldAddress field_nullability_operand(result, Field::is_nullable_offset()); |
| 2147 | 2068 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2193 __ movups(FieldAddress(result, Float64x2::value_offset()), value); | 2114 __ movups(FieldAddress(result, Float64x2::value_offset()), value); |
| 2194 __ jmp(&done); | 2115 __ jmp(&done); |
| 2195 } | 2116 } |
| 2196 | 2117 |
| 2197 __ Bind(&load_pointer); | 2118 __ Bind(&load_pointer); |
| 2198 } | 2119 } |
| 2199 __ movl(result, FieldAddress(instance_reg, offset_in_bytes())); | 2120 __ movl(result, FieldAddress(instance_reg, offset_in_bytes())); |
| 2200 __ Bind(&done); | 2121 __ Bind(&done); |
| 2201 } | 2122 } |
| 2202 | 2123 |
| 2203 | |
| 2204 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2124 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
| 2205 bool opt) const { | 2125 bool opt) const { |
| 2206 const intptr_t kNumInputs = 2; | 2126 const intptr_t kNumInputs = 2; |
| 2207 const intptr_t kNumTemps = 0; | 2127 const intptr_t kNumTemps = 0; |
| 2208 LocationSummary* locs = new (zone) | 2128 LocationSummary* locs = new (zone) |
| 2209 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2129 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2210 locs->set_in(0, Location::RegisterLocation(EAX)); // Instant. type args. | 2130 locs->set_in(0, Location::RegisterLocation(EAX)); // Instant. type args. |
| 2211 locs->set_in(1, Location::RegisterLocation(EDX)); // Function type args. | 2131 locs->set_in(1, Location::RegisterLocation(EDX)); // Function type args. |
| 2212 locs->set_out(0, Location::RegisterLocation(EAX)); | 2132 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2213 return locs; | 2133 return locs; |
| 2214 } | 2134 } |
| 2215 | 2135 |
| 2216 | |
| 2217 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2136 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2218 Register instantiator_type_args_reg = locs()->in(0).reg(); | 2137 Register instantiator_type_args_reg = locs()->in(0).reg(); |
| 2219 Register function_type_args_reg = locs()->in(1).reg(); | 2138 Register function_type_args_reg = locs()->in(1).reg(); |
| 2220 Register result_reg = locs()->out(0).reg(); | 2139 Register result_reg = locs()->out(0).reg(); |
| 2221 | 2140 |
| 2222 // 'instantiator_type_args_reg' is a TypeArguments object (or null). | 2141 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
| 2223 // 'function_type_args_reg' is a TypeArguments object (or null). | 2142 // 'function_type_args_reg' is a TypeArguments object (or null). |
| 2224 // A runtime call to instantiate the type is required. | 2143 // A runtime call to instantiate the type is required. |
| 2225 __ PushObject(Object::null_object()); // Make room for the result. | 2144 __ PushObject(Object::null_object()); // Make room for the result. |
| 2226 __ PushObject(type()); | 2145 __ PushObject(type()); |
| 2227 __ pushl(instantiator_type_args_reg); // Push instantiator type arguments. | 2146 __ pushl(instantiator_type_args_reg); // Push instantiator type arguments. |
| 2228 __ pushl(function_type_args_reg); // Push function type arguments. | 2147 __ pushl(function_type_args_reg); // Push function type arguments. |
| 2229 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2148 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2230 kInstantiateTypeRuntimeEntry, 3, locs()); | 2149 kInstantiateTypeRuntimeEntry, 3, locs()); |
| 2231 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. | 2150 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. |
| 2232 __ popl(result_reg); // Pop instantiated type. | 2151 __ popl(result_reg); // Pop instantiated type. |
| 2233 ASSERT(instantiator_type_args_reg == result_reg); | 2152 ASSERT(instantiator_type_args_reg == result_reg); |
| 2234 } | 2153 } |
| 2235 | 2154 |
| 2236 | |
| 2237 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2155 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2238 Zone* zone, | 2156 Zone* zone, |
| 2239 bool opt) const { | 2157 bool opt) const { |
| 2240 const intptr_t kNumInputs = 2; | 2158 const intptr_t kNumInputs = 2; |
| 2241 const intptr_t kNumTemps = 0; | 2159 const intptr_t kNumTemps = 0; |
| 2242 LocationSummary* locs = new (zone) | 2160 LocationSummary* locs = new (zone) |
| 2243 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2161 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2244 locs->set_in(0, Location::RegisterLocation(EAX)); // Instant. type args. | 2162 locs->set_in(0, Location::RegisterLocation(EAX)); // Instant. type args. |
| 2245 locs->set_in(1, Location::RegisterLocation(ECX)); // Function type args. | 2163 locs->set_in(1, Location::RegisterLocation(ECX)); // Function type args. |
| 2246 locs->set_out(0, Location::RegisterLocation(EAX)); | 2164 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2247 return locs; | 2165 return locs; |
| 2248 } | 2166 } |
| 2249 | 2167 |
| 2250 | |
| 2251 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2168 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2252 FlowGraphCompiler* compiler) { | 2169 FlowGraphCompiler* compiler) { |
| 2253 Register instantiator_type_args_reg = locs()->in(0).reg(); | 2170 Register instantiator_type_args_reg = locs()->in(0).reg(); |
| 2254 Register function_type_args_reg = locs()->in(1).reg(); | 2171 Register function_type_args_reg = locs()->in(1).reg(); |
| 2255 Register result_reg = locs()->out(0).reg(); | 2172 Register result_reg = locs()->out(0).reg(); |
| 2256 ASSERT(instantiator_type_args_reg == EAX); | 2173 ASSERT(instantiator_type_args_reg == EAX); |
| 2257 ASSERT(instantiator_type_args_reg == result_reg); | 2174 ASSERT(instantiator_type_args_reg == result_reg); |
| 2258 | 2175 |
| 2259 // 'instantiator_type_args_reg' is a TypeArguments object (or null). | 2176 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
| 2260 // 'function_type_args_reg' is a TypeArguments object (or null). | 2177 // 'function_type_args_reg' is a TypeArguments object (or null). |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2309 __ pushl(instantiator_type_args_reg); // Push instantiator type arguments. | 2226 __ pushl(instantiator_type_args_reg); // Push instantiator type arguments. |
| 2310 __ pushl(function_type_args_reg); // Push function type arguments. | 2227 __ pushl(function_type_args_reg); // Push function type arguments. |
| 2311 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2228 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2312 kInstantiateTypeArgumentsRuntimeEntry, 3, | 2229 kInstantiateTypeArgumentsRuntimeEntry, 3, |
| 2313 locs()); | 2230 locs()); |
| 2314 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. | 2231 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. |
| 2315 __ popl(result_reg); // Pop instantiated type arguments. | 2232 __ popl(result_reg); // Pop instantiated type arguments. |
| 2316 __ Bind(&type_arguments_instantiated); | 2233 __ Bind(&type_arguments_instantiated); |
| 2317 } | 2234 } |
| 2318 | 2235 |
| 2319 | |
| 2320 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2236 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
| 2321 Zone* zone, | 2237 Zone* zone, |
| 2322 bool opt) const { | 2238 bool opt) const { |
| 2323 ASSERT(opt); | 2239 ASSERT(opt); |
| 2324 const intptr_t kNumInputs = 0; | 2240 const intptr_t kNumInputs = 0; |
| 2325 const intptr_t kNumTemps = 2; | 2241 const intptr_t kNumTemps = 2; |
| 2326 LocationSummary* locs = new (zone) LocationSummary( | 2242 LocationSummary* locs = new (zone) LocationSummary( |
| 2327 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2243 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2328 locs->set_temp(0, Location::RegisterLocation(ECX)); | 2244 locs->set_temp(0, Location::RegisterLocation(ECX)); |
| 2329 locs->set_temp(1, Location::RegisterLocation(EDI)); | 2245 locs->set_temp(1, Location::RegisterLocation(EDI)); |
| 2330 locs->set_out(0, Location::RegisterLocation(EAX)); | 2246 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2331 return locs; | 2247 return locs; |
| 2332 } | 2248 } |
| 2333 | 2249 |
| 2334 | |
| 2335 class AllocateContextSlowPath : public SlowPathCode { | 2250 class AllocateContextSlowPath : public SlowPathCode { |
| 2336 public: | 2251 public: |
| 2337 explicit AllocateContextSlowPath( | 2252 explicit AllocateContextSlowPath( |
| 2338 AllocateUninitializedContextInstr* instruction) | 2253 AllocateUninitializedContextInstr* instruction) |
| 2339 : instruction_(instruction) {} | 2254 : instruction_(instruction) {} |
| 2340 | 2255 |
| 2341 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2256 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2342 __ Comment("AllocateContextSlowPath"); | 2257 __ Comment("AllocateContextSlowPath"); |
| 2343 __ Bind(entry_label()); | 2258 __ Bind(entry_label()); |
| 2344 | 2259 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2356 RawPcDescriptors::kOther, locs); | 2271 RawPcDescriptors::kOther, locs); |
| 2357 ASSERT(instruction_->locs()->out(0).reg() == EAX); | 2272 ASSERT(instruction_->locs()->out(0).reg() == EAX); |
| 2358 compiler->RestoreLiveRegisters(instruction_->locs()); | 2273 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2359 __ jmp(exit_label()); | 2274 __ jmp(exit_label()); |
| 2360 } | 2275 } |
| 2361 | 2276 |
| 2362 private: | 2277 private: |
| 2363 AllocateUninitializedContextInstr* instruction_; | 2278 AllocateUninitializedContextInstr* instruction_; |
| 2364 }; | 2279 }; |
| 2365 | 2280 |
| 2366 | |
| 2367 void AllocateUninitializedContextInstr::EmitNativeCode( | 2281 void AllocateUninitializedContextInstr::EmitNativeCode( |
| 2368 FlowGraphCompiler* compiler) { | 2282 FlowGraphCompiler* compiler) { |
| 2369 ASSERT(compiler->is_optimizing()); | 2283 ASSERT(compiler->is_optimizing()); |
| 2370 Register temp = locs()->temp(0).reg(); | 2284 Register temp = locs()->temp(0).reg(); |
| 2371 Register temp2 = locs()->temp(1).reg(); | 2285 Register temp2 = locs()->temp(1).reg(); |
| 2372 Register result = locs()->out(0).reg(); | 2286 Register result = locs()->out(0).reg(); |
| 2373 // Try allocate the object. | 2287 // Try allocate the object. |
| 2374 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2288 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2375 compiler->AddSlowPathCode(slow_path); | 2289 compiler->AddSlowPathCode(slow_path); |
| 2376 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2290 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2377 | 2291 |
| 2378 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2292 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
| 2379 Assembler::kFarJump, | 2293 Assembler::kFarJump, |
| 2380 result, // instance | 2294 result, // instance |
| 2381 temp, // end address | 2295 temp, // end address |
| 2382 temp2); // temp | 2296 temp2); // temp |
| 2383 | 2297 |
| 2384 // Setup up number of context variables field. | 2298 // Setup up number of context variables field. |
| 2385 __ movl(FieldAddress(result, Context::num_variables_offset()), | 2299 __ movl(FieldAddress(result, Context::num_variables_offset()), |
| 2386 Immediate(num_context_variables())); | 2300 Immediate(num_context_variables())); |
| 2387 | 2301 |
| 2388 __ Bind(slow_path->exit_label()); | 2302 __ Bind(slow_path->exit_label()); |
| 2389 } | 2303 } |
| 2390 | 2304 |
| 2391 | |
| 2392 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2305 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
| 2393 bool opt) const { | 2306 bool opt) const { |
| 2394 const intptr_t kNumInputs = 0; | 2307 const intptr_t kNumInputs = 0; |
| 2395 const intptr_t kNumTemps = 1; | 2308 const intptr_t kNumTemps = 1; |
| 2396 LocationSummary* locs = new (zone) | 2309 LocationSummary* locs = new (zone) |
| 2397 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2310 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2398 locs->set_temp(0, Location::RegisterLocation(EDX)); | 2311 locs->set_temp(0, Location::RegisterLocation(EDX)); |
| 2399 locs->set_out(0, Location::RegisterLocation(EAX)); | 2312 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2400 return locs; | 2313 return locs; |
| 2401 } | 2314 } |
| 2402 | 2315 |
| 2403 | |
| 2404 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2316 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2405 ASSERT(locs()->temp(0).reg() == EDX); | 2317 ASSERT(locs()->temp(0).reg() == EDX); |
| 2406 ASSERT(locs()->out(0).reg() == EAX); | 2318 ASSERT(locs()->out(0).reg() == EAX); |
| 2407 | 2319 |
| 2408 __ movl(EDX, Immediate(num_context_variables())); | 2320 __ movl(EDX, Immediate(num_context_variables())); |
| 2409 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), | 2321 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
| 2410 RawPcDescriptors::kOther, locs()); | 2322 RawPcDescriptors::kOther, locs()); |
| 2411 } | 2323 } |
| 2412 | 2324 |
| 2413 | |
| 2414 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2325 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2415 bool opt) const { | 2326 bool opt) const { |
| 2416 const intptr_t kNumInputs = 1; | 2327 const intptr_t kNumInputs = 1; |
| 2417 const intptr_t kNumTemps = 1; | 2328 const intptr_t kNumTemps = 1; |
| 2418 LocationSummary* locs = new (zone) | 2329 LocationSummary* locs = new (zone) |
| 2419 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2330 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2420 locs->set_in(0, Location::RegisterLocation(EAX)); | 2331 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 2421 locs->set_temp(0, Location::RegisterLocation(ECX)); | 2332 locs->set_temp(0, Location::RegisterLocation(ECX)); |
| 2422 return locs; | 2333 return locs; |
| 2423 } | 2334 } |
| 2424 | 2335 |
| 2425 | |
| 2426 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2336 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2427 Register field = locs()->in(0).reg(); | 2337 Register field = locs()->in(0).reg(); |
| 2428 Register temp = locs()->temp(0).reg(); | 2338 Register temp = locs()->temp(0).reg(); |
| 2429 | 2339 |
| 2430 Label call_runtime, no_call; | 2340 Label call_runtime, no_call; |
| 2431 | 2341 |
| 2432 __ movl(temp, FieldAddress(field, Field::static_value_offset())); | 2342 __ movl(temp, FieldAddress(field, Field::static_value_offset())); |
| 2433 __ CompareObject(temp, Object::sentinel()); | 2343 __ CompareObject(temp, Object::sentinel()); |
| 2434 __ j(EQUAL, &call_runtime); | 2344 __ j(EQUAL, &call_runtime); |
| 2435 | 2345 |
| 2436 __ CompareObject(temp, Object::transition_sentinel()); | 2346 __ CompareObject(temp, Object::transition_sentinel()); |
| 2437 __ j(NOT_EQUAL, &no_call); | 2347 __ j(NOT_EQUAL, &no_call); |
| 2438 | 2348 |
| 2439 __ Bind(&call_runtime); | 2349 __ Bind(&call_runtime); |
| 2440 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2350 __ PushObject(Object::null_object()); // Make room for (unused) result. |
| 2441 __ pushl(field); | 2351 __ pushl(field); |
| 2442 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2352 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2443 kInitStaticFieldRuntimeEntry, 1, locs()); | 2353 kInitStaticFieldRuntimeEntry, 1, locs()); |
| 2444 __ Drop(2); // Remove argument and unused result. | 2354 __ Drop(2); // Remove argument and unused result. |
| 2445 __ Bind(&no_call); | 2355 __ Bind(&no_call); |
| 2446 } | 2356 } |
| 2447 | 2357 |
| 2448 | |
| 2449 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2358 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
| 2450 bool opt) const { | 2359 bool opt) const { |
| 2451 const intptr_t kNumInputs = 1; | 2360 const intptr_t kNumInputs = 1; |
| 2452 const intptr_t kNumTemps = 0; | 2361 const intptr_t kNumTemps = 0; |
| 2453 LocationSummary* locs = new (zone) | 2362 LocationSummary* locs = new (zone) |
| 2454 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2363 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2455 locs->set_in(0, Location::RegisterLocation(EAX)); | 2364 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 2456 locs->set_out(0, Location::RegisterLocation(EAX)); | 2365 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 2457 return locs; | 2366 return locs; |
| 2458 } | 2367 } |
| 2459 | 2368 |
| 2460 | |
| 2461 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2369 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2462 Register context_value = locs()->in(0).reg(); | 2370 Register context_value = locs()->in(0).reg(); |
| 2463 Register result = locs()->out(0).reg(); | 2371 Register result = locs()->out(0).reg(); |
| 2464 | 2372 |
| 2465 __ PushObject(Object::null_object()); // Make room for the result. | 2373 __ PushObject(Object::null_object()); // Make room for the result. |
| 2466 __ pushl(context_value); | 2374 __ pushl(context_value); |
| 2467 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2375 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2468 kCloneContextRuntimeEntry, 1, locs()); | 2376 kCloneContextRuntimeEntry, 1, locs()); |
| 2469 __ popl(result); // Remove argument. | 2377 __ popl(result); // Remove argument. |
| 2470 __ popl(result); // Get result (cloned context). | 2378 __ popl(result); // Get result (cloned context). |
| 2471 } | 2379 } |
| 2472 | 2380 |
| 2473 | |
| 2474 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2381 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
| 2475 bool opt) const { | 2382 bool opt) const { |
| 2476 UNREACHABLE(); | 2383 UNREACHABLE(); |
| 2477 return NULL; | 2384 return NULL; |
| 2478 } | 2385 } |
| 2479 | 2386 |
| 2480 | |
| 2481 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2387 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2482 __ Bind(compiler->GetJumpLabel(this)); | 2388 __ Bind(compiler->GetJumpLabel(this)); |
| 2483 compiler->AddExceptionHandler(catch_try_index(), try_index(), | 2389 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
| 2484 compiler->assembler()->CodeSize(), | 2390 compiler->assembler()->CodeSize(), |
| 2485 handler_token_pos(), is_generated(), | 2391 handler_token_pos(), is_generated(), |
| 2486 catch_handler_types_, needs_stacktrace()); | 2392 catch_handler_types_, needs_stacktrace()); |
| 2487 // On lazy deoptimization we patch the optimized code here to enter the | 2393 // On lazy deoptimization we patch the optimized code here to enter the |
| 2488 // deoptimization stub. | 2394 // deoptimization stub. |
| 2489 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2395 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
| 2490 if (compiler->is_optimizing()) { | 2396 if (compiler->is_optimizing()) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2545 } else { | 2451 } else { |
| 2546 // Restore stack and initialize the two exception variables: | 2452 // Restore stack and initialize the two exception variables: |
| 2547 // exception and stack trace variables. | 2453 // exception and stack trace variables. |
| 2548 __ movl(Address(EBP, exception_var().index() * kWordSize), | 2454 __ movl(Address(EBP, exception_var().index() * kWordSize), |
| 2549 kExceptionObjectReg); | 2455 kExceptionObjectReg); |
| 2550 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), | 2456 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), |
| 2551 kStackTraceObjectReg); | 2457 kStackTraceObjectReg); |
| 2552 } | 2458 } |
| 2553 } | 2459 } |
| 2554 | 2460 |
| 2555 | |
| 2556 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2461 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
| 2557 bool opt) const { | 2462 bool opt) const { |
| 2558 const intptr_t kNumInputs = 0; | 2463 const intptr_t kNumInputs = 0; |
| 2559 const intptr_t kNumTemps = opt ? 0 : 1; | 2464 const intptr_t kNumTemps = opt ? 0 : 1; |
| 2560 LocationSummary* summary = new (zone) LocationSummary( | 2465 LocationSummary* summary = new (zone) LocationSummary( |
| 2561 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2466 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2562 if (!opt) { | 2467 if (!opt) { |
| 2563 summary->set_temp(0, Location::RequiresRegister()); | 2468 summary->set_temp(0, Location::RequiresRegister()); |
| 2564 } | 2469 } |
| 2565 return summary; | 2470 return summary; |
| 2566 } | 2471 } |
| 2567 | 2472 |
| 2568 | |
| 2569 class CheckStackOverflowSlowPath : public SlowPathCode { | 2473 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 2570 public: | 2474 public: |
| 2571 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2475 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 2572 : instruction_(instruction) {} | 2476 : instruction_(instruction) {} |
| 2573 | 2477 |
| 2574 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2478 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2575 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { | 2479 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { |
| 2576 __ Comment("CheckStackOverflowSlowPathOsr"); | 2480 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 2577 __ Bind(osr_entry_label()); | 2481 __ Bind(osr_entry_label()); |
| 2578 __ movl(Address(THR, Thread::stack_overflow_flags_offset()), | 2482 __ movl(Address(THR, Thread::stack_overflow_flags_offset()), |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2605 Label* osr_entry_label() { | 2509 Label* osr_entry_label() { |
| 2606 ASSERT(Isolate::Current()->use_osr()); | 2510 ASSERT(Isolate::Current()->use_osr()); |
| 2607 return &osr_entry_label_; | 2511 return &osr_entry_label_; |
| 2608 } | 2512 } |
| 2609 | 2513 |
| 2610 private: | 2514 private: |
| 2611 CheckStackOverflowInstr* instruction_; | 2515 CheckStackOverflowInstr* instruction_; |
| 2612 Label osr_entry_label_; | 2516 Label osr_entry_label_; |
| 2613 }; | 2517 }; |
| 2614 | 2518 |
| 2615 | |
| 2616 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2519 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2617 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 2520 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 2618 compiler->AddSlowPathCode(slow_path); | 2521 compiler->AddSlowPathCode(slow_path); |
| 2619 | 2522 |
| 2620 __ cmpl(ESP, Address(THR, Thread::stack_limit_offset())); | 2523 __ cmpl(ESP, Address(THR, Thread::stack_limit_offset())); |
| 2621 __ j(BELOW_EQUAL, slow_path->entry_label()); | 2524 __ j(BELOW_EQUAL, slow_path->entry_label()); |
| 2622 if (compiler->CanOSRFunction() && in_loop()) { | 2525 if (compiler->CanOSRFunction() && in_loop()) { |
| 2623 // In unoptimized code check the usage counter to trigger OSR at loop | 2526 // In unoptimized code check the usage counter to trigger OSR at loop |
| 2624 // stack checks. Use progressively higher thresholds for more deeply | 2527 // stack checks. Use progressively higher thresholds for more deeply |
| 2625 // nested loops to attempt to hit outer loops with OSR when possible. | 2528 // nested loops to attempt to hit outer loops with OSR when possible. |
| 2626 __ LoadObject(EDI, compiler->parsed_function().function()); | 2529 __ LoadObject(EDI, compiler->parsed_function().function()); |
| 2627 intptr_t threshold = | 2530 intptr_t threshold = |
| 2628 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2531 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
| 2629 __ cmpl(FieldAddress(EDI, Function::usage_counter_offset()), | 2532 __ cmpl(FieldAddress(EDI, Function::usage_counter_offset()), |
| 2630 Immediate(threshold)); | 2533 Immediate(threshold)); |
| 2631 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); | 2534 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); |
| 2632 } | 2535 } |
| 2633 if (compiler->ForceSlowPathForStackOverflow()) { | 2536 if (compiler->ForceSlowPathForStackOverflow()) { |
| 2634 // TODO(turnidge): Implement stack overflow count in assembly to | 2537 // TODO(turnidge): Implement stack overflow count in assembly to |
| 2635 // make --stacktrace-every and --deoptimize-every faster. | 2538 // make --stacktrace-every and --deoptimize-every faster. |
| 2636 __ jmp(slow_path->entry_label()); | 2539 __ jmp(slow_path->entry_label()); |
| 2637 } | 2540 } |
| 2638 __ Bind(slow_path->exit_label()); | 2541 __ Bind(slow_path->exit_label()); |
| 2639 } | 2542 } |
| 2640 | 2543 |
| 2641 | |
| 2642 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2544 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 2643 BinarySmiOpInstr* shift_left) { | 2545 BinarySmiOpInstr* shift_left) { |
| 2644 const LocationSummary& locs = *shift_left->locs(); | 2546 const LocationSummary& locs = *shift_left->locs(); |
| 2645 Register left = locs.in(0).reg(); | 2547 Register left = locs.in(0).reg(); |
| 2646 Register result = locs.out(0).reg(); | 2548 Register result = locs.out(0).reg(); |
| 2647 ASSERT(left == result); | 2549 ASSERT(left == result); |
| 2648 Label* deopt = shift_left->CanDeoptimize() | 2550 Label* deopt = shift_left->CanDeoptimize() |
| 2649 ? compiler->AddDeoptStub(shift_left->deopt_id(), | 2551 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 2650 ICData::kDeoptBinarySmiOp) | 2552 ICData::kDeoptBinarySmiOp) |
| 2651 : NULL; | 2553 : NULL; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2743 // Overflow test (preserve temp and right); | 2645 // Overflow test (preserve temp and right); |
| 2744 __ shll(left, right); | 2646 __ shll(left, right); |
| 2745 __ sarl(left, right); | 2647 __ sarl(left, right); |
| 2746 __ cmpl(left, temp); | 2648 __ cmpl(left, temp); |
| 2747 __ j(NOT_EQUAL, deopt); // Overflow. | 2649 __ j(NOT_EQUAL, deopt); // Overflow. |
| 2748 // Shift for result now we know there is no overflow. | 2650 // Shift for result now we know there is no overflow. |
| 2749 __ shll(left, right); | 2651 __ shll(left, right); |
| 2750 } | 2652 } |
| 2751 } | 2653 } |
| 2752 | 2654 |
| 2753 | |
| 2754 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2655 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
| 2755 bool opt) const { | 2656 bool opt) const { |
| 2756 // Only for precompiled code, not on ia32 currently. | 2657 // Only for precompiled code, not on ia32 currently. |
| 2757 UNIMPLEMENTED(); | 2658 UNIMPLEMENTED(); |
| 2758 return NULL; | 2659 return NULL; |
| 2759 } | 2660 } |
| 2760 | 2661 |
| 2761 | |
| 2762 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2662 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2763 // Only for precompiled code, not on ia32 currently. | 2663 // Only for precompiled code, not on ia32 currently. |
| 2764 UNIMPLEMENTED(); | 2664 UNIMPLEMENTED(); |
| 2765 } | 2665 } |
| 2766 | 2666 |
| 2767 | |
| 2768 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 2667 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
| 2769 Zone* zone, | 2668 Zone* zone, |
| 2770 bool opt) const { | 2669 bool opt) const { |
| 2771 // Only for precompiled code, not on ia32 currently. | 2670 // Only for precompiled code, not on ia32 currently. |
| 2772 UNIMPLEMENTED(); | 2671 UNIMPLEMENTED(); |
| 2773 return NULL; | 2672 return NULL; |
| 2774 } | 2673 } |
| 2775 | 2674 |
| 2776 | |
| 2777 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 2675 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
| 2778 FlowGraphCompiler* compiler, | 2676 FlowGraphCompiler* compiler, |
| 2779 BranchLabels labels) { | 2677 BranchLabels labels) { |
| 2780 // Only for precompiled code, not on ia32 currently. | 2678 // Only for precompiled code, not on ia32 currently. |
| 2781 UNIMPLEMENTED(); | 2679 UNIMPLEMENTED(); |
| 2782 return ZERO; | 2680 return ZERO; |
| 2783 } | 2681 } |
| 2784 | 2682 |
| 2785 | |
| 2786 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 2683 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 2787 BranchInstr* instr) { | 2684 BranchInstr* instr) { |
| 2788 // Only for precompiled code, not on ia32 currently. | 2685 // Only for precompiled code, not on ia32 currently. |
| 2789 UNIMPLEMENTED(); | 2686 UNIMPLEMENTED(); |
| 2790 } | 2687 } |
| 2791 | 2688 |
| 2792 | |
| 2793 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2689 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2794 // Only for precompiled code, not on ia32 currently. | 2690 // Only for precompiled code, not on ia32 currently. |
| 2795 UNIMPLEMENTED(); | 2691 UNIMPLEMENTED(); |
| 2796 } | 2692 } |
| 2797 | 2693 |
| 2798 | |
| 2799 static bool IsSmiValue(const Object& constant, intptr_t value) { | 2694 static bool IsSmiValue(const Object& constant, intptr_t value) { |
| 2800 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); | 2695 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); |
| 2801 } | 2696 } |
| 2802 | 2697 |
| 2803 | |
| 2804 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 2698 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 2805 bool opt) const { | 2699 bool opt) const { |
| 2806 const intptr_t kNumInputs = 2; | 2700 const intptr_t kNumInputs = 2; |
| 2807 if (op_kind() == Token::kTRUNCDIV) { | 2701 if (op_kind() == Token::kTRUNCDIV) { |
| 2808 const intptr_t kNumTemps = 1; | 2702 const intptr_t kNumTemps = 1; |
| 2809 LocationSummary* summary = new (zone) | 2703 LocationSummary* summary = new (zone) |
| 2810 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2704 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2811 if (RightIsPowerOfTwoConstant()) { | 2705 if (RightIsPowerOfTwoConstant()) { |
| 2812 summary->set_in(0, Location::RequiresRegister()); | 2706 summary->set_in(0, Location::RequiresRegister()); |
| 2813 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 2707 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2867 if (constant != NULL) { | 2761 if (constant != NULL) { |
| 2868 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 2762 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 2869 } else { | 2763 } else { |
| 2870 summary->set_in(1, Location::PrefersRegister()); | 2764 summary->set_in(1, Location::PrefersRegister()); |
| 2871 } | 2765 } |
| 2872 summary->set_out(0, Location::SameAsFirstInput()); | 2766 summary->set_out(0, Location::SameAsFirstInput()); |
| 2873 return summary; | 2767 return summary; |
| 2874 } | 2768 } |
| 2875 } | 2769 } |
| 2876 | 2770 |
| 2877 | |
| 2878 template <typename OperandType> | 2771 template <typename OperandType> |
| 2879 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, | 2772 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, |
| 2880 Token::Kind op_kind, | 2773 Token::Kind op_kind, |
| 2881 Register left, | 2774 Register left, |
| 2882 const OperandType& right, | 2775 const OperandType& right, |
| 2883 Label* deopt) { | 2776 Label* deopt) { |
| 2884 switch (op_kind) { | 2777 switch (op_kind) { |
| 2885 case Token::kADD: | 2778 case Token::kADD: |
| 2886 __ addl(left, right); | 2779 __ addl(left, right); |
| 2887 break; | 2780 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2899 break; | 2792 break; |
| 2900 case Token::kMUL: | 2793 case Token::kMUL: |
| 2901 __ imull(left, right); | 2794 __ imull(left, right); |
| 2902 break; | 2795 break; |
| 2903 default: | 2796 default: |
| 2904 UNREACHABLE(); | 2797 UNREACHABLE(); |
| 2905 } | 2798 } |
| 2906 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2799 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 2907 } | 2800 } |
| 2908 | 2801 |
| 2909 | |
| 2910 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2802 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2911 if (op_kind() == Token::kSHL) { | 2803 if (op_kind() == Token::kSHL) { |
| 2912 EmitSmiShiftLeft(compiler, this); | 2804 EmitSmiShiftLeft(compiler, this); |
| 2913 return; | 2805 return; |
| 2914 } | 2806 } |
| 2915 | 2807 |
| 2916 Register left = locs()->in(0).reg(); | 2808 Register left = locs()->in(0).reg(); |
| 2917 Register result = locs()->out(0).reg(); | 2809 Register result = locs()->out(0).reg(); |
| 2918 ASSERT(left == result); | 2810 ASSERT(left == result); |
| 2919 Label* deopt = NULL; | 2811 Label* deopt = NULL; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2991 case Token::kBIT_AND: | 2883 case Token::kBIT_AND: |
| 2992 case Token::kBIT_OR: | 2884 case Token::kBIT_OR: |
| 2993 case Token::kBIT_XOR: | 2885 case Token::kBIT_XOR: |
| 2994 case Token::kMUL: | 2886 case Token::kMUL: |
| 2995 if (op_kind() == Token::kMUL) { | 2887 if (op_kind() == Token::kMUL) { |
| 2996 __ SmiUntag(left); | 2888 __ SmiUntag(left); |
| 2997 } | 2889 } |
| 2998 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); | 2890 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); |
| 2999 break; | 2891 break; |
| 3000 | 2892 |
| 3001 | |
| 3002 case Token::kTRUNCDIV: { | 2893 case Token::kTRUNCDIV: { |
| 3003 if (RangeUtils::CanBeZero(right_range())) { | 2894 if (RangeUtils::CanBeZero(right_range())) { |
| 3004 // Handle divide by zero in runtime. | 2895 // Handle divide by zero in runtime. |
| 3005 __ testl(right, right); | 2896 __ testl(right, right); |
| 3006 __ j(ZERO, deopt); | 2897 __ j(ZERO, deopt); |
| 3007 } | 2898 } |
| 3008 ASSERT(left == EAX); | 2899 ASSERT(left == EAX); |
| 3009 ASSERT((right != EDX) && (right != EAX)); | 2900 ASSERT((right != EDX) && (right != EAX)); |
| 3010 ASSERT(locs()->temp(0).reg() == EDX); | 2901 ASSERT(locs()->temp(0).reg() == EDX); |
| 3011 ASSERT(result == EAX); | 2902 ASSERT(result == EAX); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3100 // behavior (short-circuit evaluation). | 2991 // behavior (short-circuit evaluation). |
| 3101 UNREACHABLE(); | 2992 UNREACHABLE(); |
| 3102 break; | 2993 break; |
| 3103 } | 2994 } |
| 3104 default: | 2995 default: |
| 3105 UNREACHABLE(); | 2996 UNREACHABLE(); |
| 3106 break; | 2997 break; |
| 3107 } | 2998 } |
| 3108 } | 2999 } |
| 3109 | 3000 |
| 3110 | |
| 3111 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, | 3001 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, |
| 3112 bool opt) const { | 3002 bool opt) const { |
| 3113 const intptr_t kNumInputs = 2; | 3003 const intptr_t kNumInputs = 2; |
| 3114 if (op_kind() == Token::kTRUNCDIV) { | 3004 if (op_kind() == Token::kTRUNCDIV) { |
| 3115 UNREACHABLE(); | 3005 UNREACHABLE(); |
| 3116 return NULL; | 3006 return NULL; |
| 3117 } else if (op_kind() == Token::kMOD) { | 3007 } else if (op_kind() == Token::kMOD) { |
| 3118 UNREACHABLE(); | 3008 UNREACHABLE(); |
| 3119 return NULL; | 3009 return NULL; |
| 3120 } else if (op_kind() == Token::kSHR) { | 3010 } else if (op_kind() == Token::kSHR) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3145 if (constant != NULL) { | 3035 if (constant != NULL) { |
| 3146 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 3036 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 3147 } else { | 3037 } else { |
| 3148 summary->set_in(1, Location::PrefersRegister()); | 3038 summary->set_in(1, Location::PrefersRegister()); |
| 3149 } | 3039 } |
| 3150 summary->set_out(0, Location::SameAsFirstInput()); | 3040 summary->set_out(0, Location::SameAsFirstInput()); |
| 3151 return summary; | 3041 return summary; |
| 3152 } | 3042 } |
| 3153 } | 3043 } |
| 3154 | 3044 |
| 3155 | |
| 3156 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, | 3045 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, |
| 3157 BinaryInt32OpInstr* shift_left) { | 3046 BinaryInt32OpInstr* shift_left) { |
| 3158 const LocationSummary& locs = *shift_left->locs(); | 3047 const LocationSummary& locs = *shift_left->locs(); |
| 3159 Register left = locs.in(0).reg(); | 3048 Register left = locs.in(0).reg(); |
| 3160 Register result = locs.out(0).reg(); | 3049 Register result = locs.out(0).reg(); |
| 3161 ASSERT(left == result); | 3050 ASSERT(left == result); |
| 3162 Label* deopt = shift_left->CanDeoptimize() | 3051 Label* deopt = shift_left->CanDeoptimize() |
| 3163 ? compiler->AddDeoptStub(shift_left->deopt_id(), | 3052 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 3164 ICData::kDeoptBinarySmiOp) | 3053 ICData::kDeoptBinarySmiOp) |
| 3165 : NULL; | 3054 : NULL; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3177 __ movl(temp, left); | 3066 __ movl(temp, left); |
| 3178 __ shll(left, Immediate(value)); | 3067 __ shll(left, Immediate(value)); |
| 3179 __ sarl(left, Immediate(value)); | 3068 __ sarl(left, Immediate(value)); |
| 3180 __ cmpl(left, temp); | 3069 __ cmpl(left, temp); |
| 3181 __ j(NOT_EQUAL, deopt); // Overflow. | 3070 __ j(NOT_EQUAL, deopt); // Overflow. |
| 3182 } | 3071 } |
| 3183 // Shift for result now we know there is no overflow. | 3072 // Shift for result now we know there is no overflow. |
| 3184 __ shll(left, Immediate(value)); | 3073 __ shll(left, Immediate(value)); |
| 3185 } | 3074 } |
| 3186 | 3075 |
| 3187 | |
| 3188 void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3076 void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3189 if (op_kind() == Token::kSHL) { | 3077 if (op_kind() == Token::kSHL) { |
| 3190 EmitInt32ShiftLeft(compiler, this); | 3078 EmitInt32ShiftLeft(compiler, this); |
| 3191 return; | 3079 return; |
| 3192 } | 3080 } |
| 3193 | 3081 |
| 3194 Register left = locs()->in(0).reg(); | 3082 Register left = locs()->in(0).reg(); |
| 3195 Register result = locs()->out(0).reg(); | 3083 Register result = locs()->out(0).reg(); |
| 3196 ASSERT(left == result); | 3084 ASSERT(left == result); |
| 3197 Label* deopt = NULL; | 3085 Label* deopt = NULL; |
| 3198 if (CanDeoptimize()) { | 3086 if (CanDeoptimize()) { |
| 3199 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 3087 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
| 3200 } | 3088 } |
| 3201 | 3089 |
| 3202 if (locs()->in(1).IsConstant()) { | 3090 if (locs()->in(1).IsConstant()) { |
| 3203 const Object& constant = locs()->in(1).constant(); | 3091 const Object& constant = locs()->in(1).constant(); |
| 3204 ASSERT(constant.IsSmi()); | 3092 ASSERT(constant.IsSmi()); |
| 3205 const intptr_t value = Smi::Cast(constant).Value(); | 3093 const intptr_t value = Smi::Cast(constant).Value(); |
| 3206 switch (op_kind()) { | 3094 switch (op_kind()) { |
| 3207 case Token::kADD: | 3095 case Token::kADD: |
| 3208 case Token::kSUB: | 3096 case Token::kSUB: |
| 3209 case Token::kMUL: | 3097 case Token::kMUL: |
| 3210 case Token::kBIT_AND: | 3098 case Token::kBIT_AND: |
| 3211 case Token::kBIT_OR: | 3099 case Token::kBIT_OR: |
| 3212 case Token::kBIT_XOR: | 3100 case Token::kBIT_XOR: |
| 3213 EmitIntegerArithmetic(compiler, op_kind(), left, Immediate(value), | 3101 EmitIntegerArithmetic(compiler, op_kind(), left, Immediate(value), |
| 3214 deopt); | 3102 deopt); |
| 3215 break; | 3103 break; |
| 3216 | 3104 |
| 3217 | |
| 3218 case Token::kTRUNCDIV: { | 3105 case Token::kTRUNCDIV: { |
| 3219 UNREACHABLE(); | 3106 UNREACHABLE(); |
| 3220 break; | 3107 break; |
| 3221 } | 3108 } |
| 3222 | 3109 |
| 3223 case Token::kSHR: { | 3110 case Token::kSHR: { |
| 3224 // sarl operation masks the count to 5 bits. | 3111 // sarl operation masks the count to 5 bits. |
| 3225 const intptr_t kCountLimit = 0x1F; | 3112 const intptr_t kCountLimit = 0x1F; |
| 3226 __ sarl(left, Immediate(Utils::Minimum(value, kCountLimit))); | 3113 __ sarl(left, Immediate(Utils::Minimum(value, kCountLimit))); |
| 3227 break; | 3114 break; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3251 case Token::kBIT_XOR: | 3138 case Token::kBIT_XOR: |
| 3252 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); | 3139 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); |
| 3253 break; | 3140 break; |
| 3254 | 3141 |
| 3255 default: | 3142 default: |
| 3256 UNREACHABLE(); | 3143 UNREACHABLE(); |
| 3257 break; | 3144 break; |
| 3258 } | 3145 } |
| 3259 } | 3146 } |
| 3260 | 3147 |
| 3261 | |
| 3262 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 3148 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 3263 bool opt) const { | 3149 bool opt) const { |
| 3264 const intptr_t kNumInputs = 2; | 3150 const intptr_t kNumInputs = 2; |
| 3265 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; | 3151 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
| 3266 LocationSummary* summary = new (zone) | 3152 LocationSummary* summary = new (zone) |
| 3267 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3153 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3268 if (op_kind() == Token::kMUL) { | 3154 if (op_kind() == Token::kMUL) { |
| 3269 summary->set_in(0, Location::RegisterLocation(EAX)); | 3155 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 3270 summary->set_temp(0, Location::RegisterLocation(EDX)); | 3156 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 3271 } else { | 3157 } else { |
| 3272 summary->set_in(0, Location::RequiresRegister()); | 3158 summary->set_in(0, Location::RequiresRegister()); |
| 3273 } | 3159 } |
| 3274 summary->set_in(1, Location::RequiresRegister()); | 3160 summary->set_in(1, Location::RequiresRegister()); |
| 3275 summary->set_out(0, Location::SameAsFirstInput()); | 3161 summary->set_out(0, Location::SameAsFirstInput()); |
| 3276 return summary; | 3162 return summary; |
| 3277 } | 3163 } |
| 3278 | 3164 |
| 3279 | |
| 3280 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3165 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3281 Register left = locs()->in(0).reg(); | 3166 Register left = locs()->in(0).reg(); |
| 3282 Register right = locs()->in(1).reg(); | 3167 Register right = locs()->in(1).reg(); |
| 3283 Register out = locs()->out(0).reg(); | 3168 Register out = locs()->out(0).reg(); |
| 3284 ASSERT(out == left); | 3169 ASSERT(out == left); |
| 3285 switch (op_kind()) { | 3170 switch (op_kind()) { |
| 3286 case Token::kBIT_AND: | 3171 case Token::kBIT_AND: |
| 3287 case Token::kBIT_OR: | 3172 case Token::kBIT_OR: |
| 3288 case Token::kBIT_XOR: | 3173 case Token::kBIT_XOR: |
| 3289 case Token::kADD: | 3174 case Token::kADD: |
| 3290 case Token::kSUB: | 3175 case Token::kSUB: |
| 3291 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); | 3176 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); |
| 3292 return; | 3177 return; |
| 3293 | 3178 |
| 3294 case Token::kMUL: | 3179 case Token::kMUL: |
| 3295 __ mull(right); // Result in EDX:EAX. | 3180 __ mull(right); // Result in EDX:EAX. |
| 3296 ASSERT(out == EAX); | 3181 ASSERT(out == EAX); |
| 3297 ASSERT(locs()->temp(0).reg() == EDX); | 3182 ASSERT(locs()->temp(0).reg() == EDX); |
| 3298 break; | 3183 break; |
| 3299 default: | 3184 default: |
| 3300 UNREACHABLE(); | 3185 UNREACHABLE(); |
| 3301 } | 3186 } |
| 3302 } | 3187 } |
| 3303 | 3188 |
| 3304 | |
| 3305 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3189 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
| 3306 bool opt) const { | 3190 bool opt) const { |
| 3307 intptr_t left_cid = left()->Type()->ToCid(); | 3191 intptr_t left_cid = left()->Type()->ToCid(); |
| 3308 intptr_t right_cid = right()->Type()->ToCid(); | 3192 intptr_t right_cid = right()->Type()->ToCid(); |
| 3309 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3193 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
| 3310 const intptr_t kNumInputs = 2; | 3194 const intptr_t kNumInputs = 2; |
| 3311 const bool need_temp = (left()->definition() != right()->definition()) && | 3195 const bool need_temp = (left()->definition() != right()->definition()) && |
| 3312 (left_cid != kSmiCid) && (right_cid != kSmiCid); | 3196 (left_cid != kSmiCid) && (right_cid != kSmiCid); |
| 3313 const intptr_t kNumTemps = need_temp ? 1 : 0; | 3197 const intptr_t kNumTemps = need_temp ? 1 : 0; |
| 3314 LocationSummary* summary = new (zone) | 3198 LocationSummary* summary = new (zone) |
| 3315 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3199 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3316 summary->set_in(0, Location::RequiresRegister()); | 3200 summary->set_in(0, Location::RequiresRegister()); |
| 3317 summary->set_in(1, Location::RequiresRegister()); | 3201 summary->set_in(1, Location::RequiresRegister()); |
| 3318 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); | 3202 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); |
| 3319 return summary; | 3203 return summary; |
| 3320 } | 3204 } |
| 3321 | 3205 |
| 3322 | |
| 3323 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3206 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3324 Label* deopt = | 3207 Label* deopt = |
| 3325 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, | 3208 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
| 3326 licm_hoisted_ ? ICData::kHoisted : 0); | 3209 licm_hoisted_ ? ICData::kHoisted : 0); |
| 3327 intptr_t left_cid = left()->Type()->ToCid(); | 3210 intptr_t left_cid = left()->Type()->ToCid(); |
| 3328 intptr_t right_cid = right()->Type()->ToCid(); | 3211 intptr_t right_cid = right()->Type()->ToCid(); |
| 3329 Register left = locs()->in(0).reg(); | 3212 Register left = locs()->in(0).reg(); |
| 3330 Register right = locs()->in(1).reg(); | 3213 Register right = locs()->in(1).reg(); |
| 3331 if (this->left()->definition() == this->right()->definition()) { | 3214 if (this->left()->definition() == this->right()->definition()) { |
| 3332 __ testl(left, Immediate(kSmiTagMask)); | 3215 __ testl(left, Immediate(kSmiTagMask)); |
| 3333 } else if (left_cid == kSmiCid) { | 3216 } else if (left_cid == kSmiCid) { |
| 3334 __ testl(right, Immediate(kSmiTagMask)); | 3217 __ testl(right, Immediate(kSmiTagMask)); |
| 3335 } else if (right_cid == kSmiCid) { | 3218 } else if (right_cid == kSmiCid) { |
| 3336 __ testl(left, Immediate(kSmiTagMask)); | 3219 __ testl(left, Immediate(kSmiTagMask)); |
| 3337 } else { | 3220 } else { |
| 3338 Register temp = locs()->temp(0).reg(); | 3221 Register temp = locs()->temp(0).reg(); |
| 3339 __ movl(temp, left); | 3222 __ movl(temp, left); |
| 3340 __ orl(temp, right); | 3223 __ orl(temp, right); |
| 3341 __ testl(temp, Immediate(kSmiTagMask)); | 3224 __ testl(temp, Immediate(kSmiTagMask)); |
| 3342 } | 3225 } |
| 3343 __ j(ZERO, deopt); | 3226 __ j(ZERO, deopt); |
| 3344 } | 3227 } |
| 3345 | 3228 |
| 3346 | |
| 3347 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 3229 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3348 const intptr_t kNumInputs = 1; | 3230 const intptr_t kNumInputs = 1; |
| 3349 const intptr_t kNumTemps = 1; | 3231 const intptr_t kNumTemps = 1; |
| 3350 LocationSummary* summary = new (zone) LocationSummary( | 3232 LocationSummary* summary = new (zone) LocationSummary( |
| 3351 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3233 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3352 summary->set_in(0, Location::RequiresFpuRegister()); | 3234 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3353 summary->set_temp(0, Location::RequiresRegister()); | 3235 summary->set_temp(0, Location::RequiresRegister()); |
| 3354 summary->set_out(0, Location::RequiresRegister()); | 3236 summary->set_out(0, Location::RequiresRegister()); |
| 3355 return summary; | 3237 return summary; |
| 3356 } | 3238 } |
| 3357 | 3239 |
| 3358 | |
| 3359 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3240 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3360 Register out_reg = locs()->out(0).reg(); | 3241 Register out_reg = locs()->out(0).reg(); |
| 3361 XmmRegister value = locs()->in(0).fpu_reg(); | 3242 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3362 | 3243 |
| 3363 BoxAllocationSlowPath::Allocate(compiler, this, | 3244 BoxAllocationSlowPath::Allocate(compiler, this, |
| 3364 compiler->BoxClassFor(from_representation()), | 3245 compiler->BoxClassFor(from_representation()), |
| 3365 out_reg, locs()->temp(0).reg()); | 3246 out_reg, locs()->temp(0).reg()); |
| 3366 | 3247 |
| 3367 switch (from_representation()) { | 3248 switch (from_representation()) { |
| 3368 case kUnboxedDouble: | 3249 case kUnboxedDouble: |
| 3369 __ movsd(FieldAddress(out_reg, ValueOffset()), value); | 3250 __ movsd(FieldAddress(out_reg, ValueOffset()), value); |
| 3370 break; | 3251 break; |
| 3371 case kUnboxedFloat32x4: | 3252 case kUnboxedFloat32x4: |
| 3372 case kUnboxedFloat64x2: | 3253 case kUnboxedFloat64x2: |
| 3373 case kUnboxedInt32x4: | 3254 case kUnboxedInt32x4: |
| 3374 __ movups(FieldAddress(out_reg, ValueOffset()), value); | 3255 __ movups(FieldAddress(out_reg, ValueOffset()), value); |
| 3375 break; | 3256 break; |
| 3376 default: | 3257 default: |
| 3377 UNREACHABLE(); | 3258 UNREACHABLE(); |
| 3378 break; | 3259 break; |
| 3379 } | 3260 } |
| 3380 } | 3261 } |
| 3381 | 3262 |
| 3382 | |
| 3383 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 3263 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3384 const bool needs_temp = | 3264 const bool needs_temp = |
| 3385 CanDeoptimize() || | 3265 CanDeoptimize() || |
| 3386 (CanConvertSmi() && (value()->Type()->ToCid() == kSmiCid)); | 3266 (CanConvertSmi() && (value()->Type()->ToCid() == kSmiCid)); |
| 3387 | 3267 |
| 3388 const intptr_t kNumInputs = 1; | 3268 const intptr_t kNumInputs = 1; |
| 3389 const intptr_t kNumTemps = needs_temp ? 1 : 0; | 3269 const intptr_t kNumTemps = needs_temp ? 1 : 0; |
| 3390 LocationSummary* summary = new (zone) | 3270 LocationSummary* summary = new (zone) |
| 3391 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3271 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3392 summary->set_in(0, Location::RequiresRegister()); | 3272 summary->set_in(0, Location::RequiresRegister()); |
| 3393 if (needs_temp) { | 3273 if (needs_temp) { |
| 3394 summary->set_temp(0, Location::RequiresRegister()); | 3274 summary->set_temp(0, Location::RequiresRegister()); |
| 3395 } | 3275 } |
| 3396 if (representation() == kUnboxedMint) { | 3276 if (representation() == kUnboxedMint) { |
| 3397 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 3277 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
| 3398 Location::RegisterLocation(EDX))); | 3278 Location::RegisterLocation(EDX))); |
| 3399 } else { | 3279 } else { |
| 3400 summary->set_out(0, Location::RequiresFpuRegister()); | 3280 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3401 } | 3281 } |
| 3402 return summary; | 3282 return summary; |
| 3403 } | 3283 } |
| 3404 | 3284 |
| 3405 | |
| 3406 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3285 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
| 3407 const Register box = locs()->in(0).reg(); | 3286 const Register box = locs()->in(0).reg(); |
| 3408 | 3287 |
| 3409 switch (representation()) { | 3288 switch (representation()) { |
| 3410 case kUnboxedMint: { | 3289 case kUnboxedMint: { |
| 3411 PairLocation* result = locs()->out(0).AsPairLocation(); | 3290 PairLocation* result = locs()->out(0).AsPairLocation(); |
| 3412 __ movl(result->At(0).reg(), FieldAddress(box, ValueOffset())); | 3291 __ movl(result->At(0).reg(), FieldAddress(box, ValueOffset())); |
| 3413 __ movl(result->At(1).reg(), | 3292 __ movl(result->At(1).reg(), |
| 3414 FieldAddress(box, ValueOffset() + kWordSize)); | 3293 FieldAddress(box, ValueOffset() + kWordSize)); |
| 3415 break; | 3294 break; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3428 __ movups(result, FieldAddress(box, ValueOffset())); | 3307 __ movups(result, FieldAddress(box, ValueOffset())); |
| 3429 break; | 3308 break; |
| 3430 } | 3309 } |
| 3431 | 3310 |
| 3432 default: | 3311 default: |
| 3433 UNREACHABLE(); | 3312 UNREACHABLE(); |
| 3434 break; | 3313 break; |
| 3435 } | 3314 } |
| 3436 } | 3315 } |
| 3437 | 3316 |
| 3438 | |
| 3439 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { | 3317 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { |
| 3440 const Register box = locs()->in(0).reg(); | 3318 const Register box = locs()->in(0).reg(); |
| 3441 | 3319 |
| 3442 switch (representation()) { | 3320 switch (representation()) { |
| 3443 case kUnboxedMint: { | 3321 case kUnboxedMint: { |
| 3444 PairLocation* result = locs()->out(0).AsPairLocation(); | 3322 PairLocation* result = locs()->out(0).AsPairLocation(); |
| 3445 ASSERT(result->At(0).reg() == EAX); | 3323 ASSERT(result->At(0).reg() == EAX); |
| 3446 ASSERT(result->At(1).reg() == EDX); | 3324 ASSERT(result->At(1).reg() == EDX); |
| 3447 __ movl(EAX, box); | 3325 __ movl(EAX, box); |
| 3448 __ SmiUntag(EAX); | 3326 __ SmiUntag(EAX); |
| 3449 __ cdq(); | 3327 __ cdq(); |
| 3450 break; | 3328 break; |
| 3451 } | 3329 } |
| 3452 | 3330 |
| 3453 case kUnboxedDouble: { | 3331 case kUnboxedDouble: { |
| 3454 const Register temp = locs()->temp(0).reg(); | 3332 const Register temp = locs()->temp(0).reg(); |
| 3455 const FpuRegister result = locs()->out(0).fpu_reg(); | 3333 const FpuRegister result = locs()->out(0).fpu_reg(); |
| 3456 __ movl(temp, box); | 3334 __ movl(temp, box); |
| 3457 __ SmiUntag(temp); | 3335 __ SmiUntag(temp); |
| 3458 __ cvtsi2sd(result, temp); | 3336 __ cvtsi2sd(result, temp); |
| 3459 break; | 3337 break; |
| 3460 } | 3338 } |
| 3461 | 3339 |
| 3462 default: | 3340 default: |
| 3463 UNREACHABLE(); | 3341 UNREACHABLE(); |
| 3464 break; | 3342 break; |
| 3465 } | 3343 } |
| 3466 } | 3344 } |
| 3467 | 3345 |
| 3468 | |
| 3469 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3346 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3470 const intptr_t value_cid = value()->Type()->ToCid(); | 3347 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3471 const intptr_t box_cid = BoxCid(); | 3348 const intptr_t box_cid = BoxCid(); |
| 3472 | 3349 |
| 3473 if (value_cid == box_cid) { | 3350 if (value_cid == box_cid) { |
| 3474 EmitLoadFromBox(compiler); | 3351 EmitLoadFromBox(compiler); |
| 3475 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3352 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
| 3476 EmitSmiConversion(compiler); | 3353 EmitSmiConversion(compiler); |
| 3477 } else { | 3354 } else { |
| 3478 const Register box = locs()->in(0).reg(); | 3355 const Register box = locs()->in(0).reg(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3499 if (is_smi.IsLinked()) { | 3376 if (is_smi.IsLinked()) { |
| 3500 Label done; | 3377 Label done; |
| 3501 __ jmp(&done); | 3378 __ jmp(&done); |
| 3502 __ Bind(&is_smi); | 3379 __ Bind(&is_smi); |
| 3503 EmitSmiConversion(compiler); | 3380 EmitSmiConversion(compiler); |
| 3504 __ Bind(&done); | 3381 __ Bind(&done); |
| 3505 } | 3382 } |
| 3506 } | 3383 } |
| 3507 } | 3384 } |
| 3508 | 3385 |
| 3509 | |
| 3510 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3386 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3511 bool opt) const { | 3387 bool opt) const { |
| 3512 const intptr_t kNumInputs = 1; | 3388 const intptr_t kNumInputs = 1; |
| 3513 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3389 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 3514 LocationSummary* summary = new (zone) | 3390 LocationSummary* summary = new (zone) |
| 3515 LocationSummary(zone, kNumInputs, kNumTemps, | 3391 LocationSummary(zone, kNumInputs, kNumTemps, |
| 3516 ValueFitsSmi() ? LocationSummary::kNoCall | 3392 ValueFitsSmi() ? LocationSummary::kNoCall |
| 3517 : LocationSummary::kCallOnSlowPath); | 3393 : LocationSummary::kCallOnSlowPath); |
| 3518 const bool needs_writable_input = | 3394 const bool needs_writable_input = |
| 3519 ValueFitsSmi() || (from_representation() == kUnboxedUint32); | 3395 ValueFitsSmi() || (from_representation() == kUnboxedUint32); |
| 3520 summary->set_in(0, needs_writable_input ? Location::RequiresRegister() | 3396 summary->set_in(0, needs_writable_input ? Location::RequiresRegister() |
| 3521 : Location::WritableRegister()); | 3397 : Location::WritableRegister()); |
| 3522 if (!ValueFitsSmi()) { | 3398 if (!ValueFitsSmi()) { |
| 3523 summary->set_temp(0, Location::RequiresRegister()); | 3399 summary->set_temp(0, Location::RequiresRegister()); |
| 3524 } | 3400 } |
| 3525 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() | 3401 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() |
| 3526 : Location::RequiresRegister()); | 3402 : Location::RequiresRegister()); |
| 3527 return summary; | 3403 return summary; |
| 3528 } | 3404 } |
| 3529 | 3405 |
| 3530 | |
| 3531 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3406 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3532 const Register value = locs()->in(0).reg(); | 3407 const Register value = locs()->in(0).reg(); |
| 3533 const Register out = locs()->out(0).reg(); | 3408 const Register out = locs()->out(0).reg(); |
| 3534 | 3409 |
| 3535 __ MoveRegister(out, value); | 3410 __ MoveRegister(out, value); |
| 3536 __ shll(out, Immediate(kSmiTagSize)); | 3411 __ shll(out, Immediate(kSmiTagSize)); |
| 3537 if (!ValueFitsSmi()) { | 3412 if (!ValueFitsSmi()) { |
| 3538 Label done; | 3413 Label done; |
| 3539 ASSERT(value != out); | 3414 ASSERT(value != out); |
| 3540 if (from_representation() == kUnboxedInt32) { | 3415 if (from_representation() == kUnboxedInt32) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3555 __ sarl(value, Immediate(31)); // Sign extend. | 3430 __ sarl(value, Immediate(31)); // Sign extend. |
| 3556 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value); | 3431 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value); |
| 3557 } else { | 3432 } else { |
| 3558 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), | 3433 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), |
| 3559 Immediate(0)); | 3434 Immediate(0)); |
| 3560 } | 3435 } |
| 3561 __ Bind(&done); | 3436 __ Bind(&done); |
| 3562 } | 3437 } |
| 3563 } | 3438 } |
| 3564 | 3439 |
| 3565 | |
| 3566 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 3440 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
| 3567 bool opt) const { | 3441 bool opt) const { |
| 3568 const intptr_t kNumInputs = 1; | 3442 const intptr_t kNumInputs = 1; |
| 3569 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3443 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 3570 LocationSummary* summary = new (zone) | 3444 LocationSummary* summary = new (zone) |
| 3571 LocationSummary(zone, kNumInputs, kNumTemps, | 3445 LocationSummary(zone, kNumInputs, kNumTemps, |
| 3572 ValueFitsSmi() ? LocationSummary::kNoCall | 3446 ValueFitsSmi() ? LocationSummary::kNoCall |
| 3573 : LocationSummary::kCallOnSlowPath); | 3447 : LocationSummary::kCallOnSlowPath); |
| 3574 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 3448 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 3575 Location::RequiresRegister())); | 3449 Location::RequiresRegister())); |
| 3576 if (!ValueFitsSmi()) { | 3450 if (!ValueFitsSmi()) { |
| 3577 summary->set_temp(0, Location::RequiresRegister()); | 3451 summary->set_temp(0, Location::RequiresRegister()); |
| 3578 } | 3452 } |
| 3579 summary->set_out(0, Location::RequiresRegister()); | 3453 summary->set_out(0, Location::RequiresRegister()); |
| 3580 return summary; | 3454 return summary; |
| 3581 } | 3455 } |
| 3582 | 3456 |
| 3583 | |
| 3584 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3457 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3585 if (ValueFitsSmi()) { | 3458 if (ValueFitsSmi()) { |
| 3586 PairLocation* value_pair = locs()->in(0).AsPairLocation(); | 3459 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
| 3587 Register value_lo = value_pair->At(0).reg(); | 3460 Register value_lo = value_pair->At(0).reg(); |
| 3588 Register out_reg = locs()->out(0).reg(); | 3461 Register out_reg = locs()->out(0).reg(); |
| 3589 __ movl(out_reg, value_lo); | 3462 __ movl(out_reg, value_lo); |
| 3590 __ SmiTag(out_reg); | 3463 __ SmiTag(out_reg); |
| 3591 return; | 3464 return; |
| 3592 } | 3465 } |
| 3593 | 3466 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3621 // 3. Restore lower half of input before using it. | 3494 // 3. Restore lower half of input before using it. |
| 3622 __ subl(value_lo, Immediate(0x40000000)); | 3495 __ subl(value_lo, Immediate(0x40000000)); |
| 3623 | 3496 |
| 3624 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), | 3497 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
| 3625 out_reg, locs()->temp(0).reg()); | 3498 out_reg, locs()->temp(0).reg()); |
| 3626 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo); | 3499 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo); |
| 3627 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi); | 3500 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi); |
| 3628 __ Bind(&done); | 3501 __ Bind(&done); |
| 3629 } | 3502 } |
| 3630 | 3503 |
| 3631 | |
| 3632 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3504 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3633 bool opt) const { | 3505 bool opt) const { |
| 3634 const intptr_t value_cid = value()->Type()->ToCid(); | 3506 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3635 const intptr_t kNumInputs = 1; | 3507 const intptr_t kNumInputs = 1; |
| 3636 intptr_t kNumTemps = 0; | 3508 intptr_t kNumTemps = 0; |
| 3637 | 3509 |
| 3638 if (CanDeoptimize()) { | 3510 if (CanDeoptimize()) { |
| 3639 if ((value_cid != kSmiCid) && (value_cid != kMintCid) && !is_truncating()) { | 3511 if ((value_cid != kSmiCid) && (value_cid != kMintCid) && !is_truncating()) { |
| 3640 kNumTemps = 2; | 3512 kNumTemps = 2; |
| 3641 } else { | 3513 } else { |
| 3642 kNumTemps = 1; | 3514 kNumTemps = 1; |
| 3643 } | 3515 } |
| 3644 } | 3516 } |
| 3645 | 3517 |
| 3646 LocationSummary* summary = new (zone) | 3518 LocationSummary* summary = new (zone) |
| 3647 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3519 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3648 summary->set_in(0, Location::RequiresRegister()); | 3520 summary->set_in(0, Location::RequiresRegister()); |
| 3649 for (int i = 0; i < kNumTemps; i++) { | 3521 for (int i = 0; i < kNumTemps; i++) { |
| 3650 summary->set_temp(i, Location::RequiresRegister()); | 3522 summary->set_temp(i, Location::RequiresRegister()); |
| 3651 } | 3523 } |
| 3652 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid)) | 3524 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid)) |
| 3653 ? Location::SameAsFirstInput() | 3525 ? Location::SameAsFirstInput() |
| 3654 : Location::RequiresRegister()); | 3526 : Location::RequiresRegister()); |
| 3655 return summary; | 3527 return summary; |
| 3656 } | 3528 } |
| 3657 | 3529 |
| 3658 | |
| 3659 static void LoadInt32FromMint(FlowGraphCompiler* compiler, | 3530 static void LoadInt32FromMint(FlowGraphCompiler* compiler, |
| 3660 Register result, | 3531 Register result, |
| 3661 const Address& lo, | 3532 const Address& lo, |
| 3662 const Address& hi, | 3533 const Address& hi, |
| 3663 Register temp, | 3534 Register temp, |
| 3664 Label* deopt) { | 3535 Label* deopt) { |
| 3665 __ movl(result, lo); | 3536 __ movl(result, lo); |
| 3666 if (deopt != NULL) { | 3537 if (deopt != NULL) { |
| 3667 ASSERT(temp != result); | 3538 ASSERT(temp != result); |
| 3668 __ movl(temp, result); | 3539 __ movl(temp, result); |
| 3669 __ sarl(temp, Immediate(31)); | 3540 __ sarl(temp, Immediate(31)); |
| 3670 __ cmpl(temp, hi); | 3541 __ cmpl(temp, hi); |
| 3671 __ j(NOT_EQUAL, deopt); | 3542 __ j(NOT_EQUAL, deopt); |
| 3672 } | 3543 } |
| 3673 } | 3544 } |
| 3674 | 3545 |
| 3675 | |
| 3676 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3546 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3677 const intptr_t value_cid = value()->Type()->ToCid(); | 3547 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3678 Register value = locs()->in(0).reg(); | 3548 Register value = locs()->in(0).reg(); |
| 3679 const Register result = locs()->out(0).reg(); | 3549 const Register result = locs()->out(0).reg(); |
| 3680 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; | 3550 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; |
| 3681 Label* deopt = | 3551 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub( |
| 3682 CanDeoptimize() | 3552 GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 3683 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) | 3553 : NULL; |
| 3684 : NULL; | |
| 3685 Label* out_of_range = !is_truncating() ? deopt : NULL; | 3554 Label* out_of_range = !is_truncating() ? deopt : NULL; |
| 3686 | 3555 |
| 3687 const intptr_t lo_offset = Mint::value_offset(); | 3556 const intptr_t lo_offset = Mint::value_offset(); |
| 3688 const intptr_t hi_offset = Mint::value_offset() + kWordSize; | 3557 const intptr_t hi_offset = Mint::value_offset() + kWordSize; |
| 3689 | 3558 |
| 3690 if (value_cid == kSmiCid) { | 3559 if (value_cid == kSmiCid) { |
| 3691 ASSERT(value == result); | 3560 ASSERT(value == result); |
| 3692 __ SmiUntag(value); | 3561 __ SmiUntag(value); |
| 3693 } else if (value_cid == kMintCid) { | 3562 } else if (value_cid == kMintCid) { |
| 3694 ASSERT((value != result) || (out_of_range == NULL)); | 3563 ASSERT((value != result) || (out_of_range == NULL)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3710 Register value_temp = locs()->temp(1).reg(); | 3579 Register value_temp = locs()->temp(1).reg(); |
| 3711 __ movl(value_temp, value); | 3580 __ movl(value_temp, value); |
| 3712 value = value_temp; | 3581 value = value_temp; |
| 3713 } | 3582 } |
| 3714 LoadInt32FromMint(compiler, result, Address(value, TIMES_2, lo_offset), | 3583 LoadInt32FromMint(compiler, result, Address(value, TIMES_2, lo_offset), |
| 3715 Address(value, TIMES_2, hi_offset), temp, out_of_range); | 3584 Address(value, TIMES_2, hi_offset), temp, out_of_range); |
| 3716 __ Bind(&done); | 3585 __ Bind(&done); |
| 3717 } | 3586 } |
| 3718 } | 3587 } |
| 3719 | 3588 |
| 3720 | |
| 3721 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 3589 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
| 3722 bool opt) const { | 3590 bool opt) const { |
| 3723 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); | 3591 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); |
| 3724 const intptr_t kNumInputs = 2; | 3592 const intptr_t kNumInputs = 2; |
| 3725 const intptr_t kNumTemps = might_box ? 2 : 0; | 3593 const intptr_t kNumTemps = might_box ? 2 : 0; |
| 3726 LocationSummary* summary = new (zone) LocationSummary( | 3594 LocationSummary* summary = new (zone) LocationSummary( |
| 3727 zone, kNumInputs, kNumTemps, | 3595 zone, kNumInputs, kNumTemps, |
| 3728 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); | 3596 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); |
| 3729 summary->set_in(0, Location::RequiresRegister()); | 3597 summary->set_in(0, Location::RequiresRegister()); |
| 3730 // The smi index is either untagged (element size == 1), or it is left smi | 3598 // The smi index is either untagged (element size == 1), or it is left smi |
| 3731 // tagged (for all element sizes > 1). | 3599 // tagged (for all element sizes > 1). |
| 3732 summary->set_in(1, (index_scale() == 1) ? Location::WritableRegister() | 3600 summary->set_in(1, (index_scale() == 1) ? Location::WritableRegister() |
| 3733 : Location::RequiresRegister()); | 3601 : Location::RequiresRegister()); |
| 3734 if (might_box) { | 3602 if (might_box) { |
| 3735 summary->set_temp(0, Location::RequiresRegister()); | 3603 summary->set_temp(0, Location::RequiresRegister()); |
| 3736 summary->set_temp(1, Location::RequiresRegister()); | 3604 summary->set_temp(1, Location::RequiresRegister()); |
| 3737 } | 3605 } |
| 3738 | 3606 |
| 3739 if (representation() == kUnboxedMint) { | 3607 if (representation() == kUnboxedMint) { |
| 3740 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 3608 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 3741 Location::RequiresRegister())); | 3609 Location::RequiresRegister())); |
| 3742 } else { | 3610 } else { |
| 3743 ASSERT(representation() == kTagged); | 3611 ASSERT(representation() == kTagged); |
| 3744 summary->set_out(0, Location::RequiresRegister()); | 3612 summary->set_out(0, Location::RequiresRegister()); |
| 3745 } | 3613 } |
| 3746 | 3614 |
| 3747 return summary; | 3615 return summary; |
| 3748 } | 3616 } |
| 3749 | 3617 |
| 3750 | |
| 3751 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3618 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3752 // The string register points to the backing store for external strings. | 3619 // The string register points to the backing store for external strings. |
| 3753 const Register str = locs()->in(0).reg(); | 3620 const Register str = locs()->in(0).reg(); |
| 3754 const Location index = locs()->in(1); | 3621 const Location index = locs()->in(1); |
| 3755 | 3622 |
| 3756 Address element_address = Assembler::ElementAddressForRegIndex( | 3623 Address element_address = Assembler::ElementAddressForRegIndex( |
| 3757 IsExternal(), class_id(), index_scale(), str, index.reg()); | 3624 IsExternal(), class_id(), index_scale(), str, index.reg()); |
| 3758 | 3625 |
| 3759 if ((index_scale() == 1)) { | 3626 if ((index_scale() == 1)) { |
| 3760 __ SmiUntag(index.reg()); | 3627 __ SmiUntag(index.reg()); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3839 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), | 3706 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
| 3840 result, temp2); | 3707 result, temp2); |
| 3841 __ movl(FieldAddress(result, Mint::value_offset()), temp); | 3708 __ movl(FieldAddress(result, Mint::value_offset()), temp); |
| 3842 __ movl(FieldAddress(result, Mint::value_offset() + kWordSize), | 3709 __ movl(FieldAddress(result, Mint::value_offset() + kWordSize), |
| 3843 Immediate(0)); | 3710 Immediate(0)); |
| 3844 __ Bind(&done); | 3711 __ Bind(&done); |
| 3845 } | 3712 } |
| 3846 } | 3713 } |
| 3847 } | 3714 } |
| 3848 | 3715 |
| 3849 | |
| 3850 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3716 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 3851 bool opt) const { | 3717 bool opt) const { |
| 3852 const intptr_t kNumInputs = 2; | 3718 const intptr_t kNumInputs = 2; |
| 3853 const intptr_t kNumTemps = 0; | 3719 const intptr_t kNumTemps = 0; |
| 3854 LocationSummary* summary = new (zone) | 3720 LocationSummary* summary = new (zone) |
| 3855 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3721 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3856 summary->set_in(0, Location::RequiresFpuRegister()); | 3722 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3857 summary->set_in(1, Location::RequiresFpuRegister()); | 3723 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3858 summary->set_out(0, Location::SameAsFirstInput()); | 3724 summary->set_out(0, Location::SameAsFirstInput()); |
| 3859 return summary; | 3725 return summary; |
| 3860 } | 3726 } |
| 3861 | 3727 |
| 3862 | |
| 3863 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3728 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3864 XmmRegister left = locs()->in(0).fpu_reg(); | 3729 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3865 XmmRegister right = locs()->in(1).fpu_reg(); | 3730 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3866 | 3731 |
| 3867 ASSERT(locs()->out(0).fpu_reg() == left); | 3732 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3868 | 3733 |
| 3869 switch (op_kind()) { | 3734 switch (op_kind()) { |
| 3870 case Token::kADD: | 3735 case Token::kADD: |
| 3871 __ addsd(left, right); | 3736 __ addsd(left, right); |
| 3872 break; | 3737 break; |
| 3873 case Token::kSUB: | 3738 case Token::kSUB: |
| 3874 __ subsd(left, right); | 3739 __ subsd(left, right); |
| 3875 break; | 3740 break; |
| 3876 case Token::kMUL: | 3741 case Token::kMUL: |
| 3877 __ mulsd(left, right); | 3742 __ mulsd(left, right); |
| 3878 break; | 3743 break; |
| 3879 case Token::kDIV: | 3744 case Token::kDIV: |
| 3880 __ divsd(left, right); | 3745 __ divsd(left, right); |
| 3881 break; | 3746 break; |
| 3882 default: | 3747 default: |
| 3883 UNREACHABLE(); | 3748 UNREACHABLE(); |
| 3884 } | 3749 } |
| 3885 } | 3750 } |
| 3886 | 3751 |
| 3887 | |
| 3888 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3752 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
| 3889 bool opt) const { | 3753 bool opt) const { |
| 3890 const intptr_t kNumInputs = 1; | 3754 const intptr_t kNumInputs = 1; |
| 3891 const intptr_t kNumTemps = | 3755 const intptr_t kNumTemps = |
| 3892 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; | 3756 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; |
| 3893 LocationSummary* summary = new (zone) | 3757 LocationSummary* summary = new (zone) |
| 3894 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3758 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3895 summary->set_in(0, Location::RequiresFpuRegister()); | 3759 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3896 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3760 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
| 3897 summary->set_temp(0, Location::RequiresRegister()); | 3761 summary->set_temp(0, Location::RequiresRegister()); |
| 3898 } | 3762 } |
| 3899 summary->set_out(0, Location::RequiresRegister()); | 3763 summary->set_out(0, Location::RequiresRegister()); |
| 3900 return summary; | 3764 return summary; |
| 3901 } | 3765 } |
| 3902 | 3766 |
| 3903 | |
| 3904 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3767 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 3905 BranchLabels labels) { | 3768 BranchLabels labels) { |
| 3906 ASSERT(compiler->is_optimizing()); | 3769 ASSERT(compiler->is_optimizing()); |
| 3907 const XmmRegister value = locs()->in(0).fpu_reg(); | 3770 const XmmRegister value = locs()->in(0).fpu_reg(); |
| 3908 const bool is_negated = kind() != Token::kEQ; | 3771 const bool is_negated = kind() != Token::kEQ; |
| 3909 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | 3772 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |
| 3910 Label is_nan; | 3773 Label is_nan; |
| 3911 __ comisd(value, value); | 3774 __ comisd(value, value); |
| 3912 return is_negated ? PARITY_ODD : PARITY_EVEN; | 3775 return is_negated ? PARITY_ODD : PARITY_EVEN; |
| 3913 } else { | 3776 } else { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3927 __ movl(temp, Address(ESP, kWordSize)); | 3790 __ movl(temp, Address(ESP, kWordSize)); |
| 3928 __ AddImmediate(ESP, Immediate(kDoubleSize)); | 3791 __ AddImmediate(ESP, Immediate(kDoubleSize)); |
| 3929 // Mask off sign bit. | 3792 // Mask off sign bit. |
| 3930 __ andl(temp, Immediate(0x7FFFFFFF)); | 3793 __ andl(temp, Immediate(0x7FFFFFFF)); |
| 3931 // Compare with +infinity. | 3794 // Compare with +infinity. |
| 3932 __ cmpl(temp, Immediate(0x7FF00000)); | 3795 __ cmpl(temp, Immediate(0x7FF00000)); |
| 3933 return is_negated ? NOT_EQUAL : EQUAL; | 3796 return is_negated ? NOT_EQUAL : EQUAL; |
| 3934 } | 3797 } |
| 3935 } | 3798 } |
| 3936 | 3799 |
| 3937 | |
| 3938 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3800 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 3939 bool opt) const { | 3801 bool opt) const { |
| 3940 const intptr_t kNumInputs = 2; | 3802 const intptr_t kNumInputs = 2; |
| 3941 const intptr_t kNumTemps = 0; | 3803 const intptr_t kNumTemps = 0; |
| 3942 LocationSummary* summary = new (zone) | 3804 LocationSummary* summary = new (zone) |
| 3943 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3805 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3944 summary->set_in(0, Location::RequiresFpuRegister()); | 3806 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3945 summary->set_in(1, Location::RequiresFpuRegister()); | 3807 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3946 summary->set_out(0, Location::SameAsFirstInput()); | 3808 summary->set_out(0, Location::SameAsFirstInput()); |
| 3947 return summary; | 3809 return summary; |
| 3948 } | 3810 } |
| 3949 | 3811 |
| 3950 | |
| 3951 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3812 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3952 XmmRegister left = locs()->in(0).fpu_reg(); | 3813 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3953 XmmRegister right = locs()->in(1).fpu_reg(); | 3814 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3954 | 3815 |
| 3955 ASSERT(locs()->out(0).fpu_reg() == left); | 3816 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3956 | 3817 |
| 3957 switch (op_kind()) { | 3818 switch (op_kind()) { |
| 3958 case Token::kADD: | 3819 case Token::kADD: |
| 3959 __ addps(left, right); | 3820 __ addps(left, right); |
| 3960 break; | 3821 break; |
| 3961 case Token::kSUB: | 3822 case Token::kSUB: |
| 3962 __ subps(left, right); | 3823 __ subps(left, right); |
| 3963 break; | 3824 break; |
| 3964 case Token::kMUL: | 3825 case Token::kMUL: |
| 3965 __ mulps(left, right); | 3826 __ mulps(left, right); |
| 3966 break; | 3827 break; |
| 3967 case Token::kDIV: | 3828 case Token::kDIV: |
| 3968 __ divps(left, right); | 3829 __ divps(left, right); |
| 3969 break; | 3830 break; |
| 3970 default: | 3831 default: |
| 3971 UNREACHABLE(); | 3832 UNREACHABLE(); |
| 3972 } | 3833 } |
| 3973 } | 3834 } |
| 3974 | 3835 |
| 3975 | |
| 3976 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 3836 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
| 3977 bool opt) const { | 3837 bool opt) const { |
| 3978 const intptr_t kNumInputs = 2; | 3838 const intptr_t kNumInputs = 2; |
| 3979 const intptr_t kNumTemps = 0; | 3839 const intptr_t kNumTemps = 0; |
| 3980 LocationSummary* summary = new (zone) | 3840 LocationSummary* summary = new (zone) |
| 3981 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3841 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3982 summary->set_in(0, Location::RequiresFpuRegister()); | 3842 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3983 summary->set_in(1, Location::RequiresFpuRegister()); | 3843 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3984 summary->set_out(0, Location::SameAsFirstInput()); | 3844 summary->set_out(0, Location::SameAsFirstInput()); |
| 3985 return summary; | 3845 return summary; |
| 3986 } | 3846 } |
| 3987 | 3847 |
| 3988 | |
| 3989 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3848 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3990 XmmRegister left = locs()->in(0).fpu_reg(); | 3849 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3991 XmmRegister right = locs()->in(1).fpu_reg(); | 3850 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3992 | 3851 |
| 3993 ASSERT(locs()->out(0).fpu_reg() == left); | 3852 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3994 | 3853 |
| 3995 switch (op_kind()) { | 3854 switch (op_kind()) { |
| 3996 case Token::kADD: | 3855 case Token::kADD: |
| 3997 __ addpd(left, right); | 3856 __ addpd(left, right); |
| 3998 break; | 3857 break; |
| 3999 case Token::kSUB: | 3858 case Token::kSUB: |
| 4000 __ subpd(left, right); | 3859 __ subpd(left, right); |
| 4001 break; | 3860 break; |
| 4002 case Token::kMUL: | 3861 case Token::kMUL: |
| 4003 __ mulpd(left, right); | 3862 __ mulpd(left, right); |
| 4004 break; | 3863 break; |
| 4005 case Token::kDIV: | 3864 case Token::kDIV: |
| 4006 __ divpd(left, right); | 3865 __ divpd(left, right); |
| 4007 break; | 3866 break; |
| 4008 default: | 3867 default: |
| 4009 UNREACHABLE(); | 3868 UNREACHABLE(); |
| 4010 } | 3869 } |
| 4011 } | 3870 } |
| 4012 | 3871 |
| 4013 | |
| 4014 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 3872 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 4015 bool opt) const { | 3873 bool opt) const { |
| 4016 const intptr_t kNumInputs = 1; | 3874 const intptr_t kNumInputs = 1; |
| 4017 const intptr_t kNumTemps = 0; | 3875 const intptr_t kNumTemps = 0; |
| 4018 LocationSummary* summary = new (zone) | 3876 LocationSummary* summary = new (zone) |
| 4019 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3877 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4020 summary->set_in(0, Location::RequiresFpuRegister()); | 3878 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4021 summary->set_out(0, Location::SameAsFirstInput()); | 3879 summary->set_out(0, Location::SameAsFirstInput()); |
| 4022 return summary; | 3880 return summary; |
| 4023 } | 3881 } |
| 4024 | 3882 |
| 4025 | |
| 4026 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3883 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4027 XmmRegister value = locs()->in(0).fpu_reg(); | 3884 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4028 | 3885 |
| 4029 ASSERT(locs()->out(0).fpu_reg() == value); | 3886 ASSERT(locs()->out(0).fpu_reg() == value); |
| 4030 | 3887 |
| 4031 switch (op_kind()) { | 3888 switch (op_kind()) { |
| 4032 case MethodRecognizer::kFloat32x4ShuffleX: | 3889 case MethodRecognizer::kFloat32x4ShuffleX: |
| 4033 // Shuffle not necessary. | 3890 // Shuffle not necessary. |
| 4034 __ cvtss2sd(value, value); | 3891 __ cvtss2sd(value, value); |
| 4035 break; | 3892 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4047 break; | 3904 break; |
| 4048 case MethodRecognizer::kFloat32x4Shuffle: | 3905 case MethodRecognizer::kFloat32x4Shuffle: |
| 4049 case MethodRecognizer::kInt32x4Shuffle: | 3906 case MethodRecognizer::kInt32x4Shuffle: |
| 4050 __ shufps(value, value, Immediate(mask_)); | 3907 __ shufps(value, value, Immediate(mask_)); |
| 4051 break; | 3908 break; |
| 4052 default: | 3909 default: |
| 4053 UNREACHABLE(); | 3910 UNREACHABLE(); |
| 4054 } | 3911 } |
| 4055 } | 3912 } |
| 4056 | 3913 |
| 4057 | |
| 4058 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 3914 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
| 4059 bool opt) const { | 3915 bool opt) const { |
| 4060 const intptr_t kNumInputs = 2; | 3916 const intptr_t kNumInputs = 2; |
| 4061 const intptr_t kNumTemps = 0; | 3917 const intptr_t kNumTemps = 0; |
| 4062 LocationSummary* summary = new (zone) | 3918 LocationSummary* summary = new (zone) |
| 4063 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3919 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4064 summary->set_in(0, Location::RequiresFpuRegister()); | 3920 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4065 summary->set_in(1, Location::RequiresFpuRegister()); | 3921 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4066 summary->set_out(0, Location::SameAsFirstInput()); | 3922 summary->set_out(0, Location::SameAsFirstInput()); |
| 4067 return summary; | 3923 return summary; |
| 4068 } | 3924 } |
| 4069 | 3925 |
| 4070 | |
| 4071 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3926 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4072 XmmRegister left = locs()->in(0).fpu_reg(); | 3927 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4073 XmmRegister right = locs()->in(1).fpu_reg(); | 3928 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4074 | 3929 |
| 4075 ASSERT(locs()->out(0).fpu_reg() == left); | 3930 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4076 switch (op_kind()) { | 3931 switch (op_kind()) { |
| 4077 case MethodRecognizer::kFloat32x4ShuffleMix: | 3932 case MethodRecognizer::kFloat32x4ShuffleMix: |
| 4078 case MethodRecognizer::kInt32x4ShuffleMix: | 3933 case MethodRecognizer::kInt32x4ShuffleMix: |
| 4079 __ shufps(left, right, Immediate(mask_)); | 3934 __ shufps(left, right, Immediate(mask_)); |
| 4080 break; | 3935 break; |
| 4081 default: | 3936 default: |
| 4082 UNREACHABLE(); | 3937 UNREACHABLE(); |
| 4083 } | 3938 } |
| 4084 } | 3939 } |
| 4085 | 3940 |
| 4086 | |
| 4087 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 3941 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
| 4088 bool opt) const { | 3942 bool opt) const { |
| 4089 const intptr_t kNumInputs = 1; | 3943 const intptr_t kNumInputs = 1; |
| 4090 const intptr_t kNumTemps = 0; | 3944 const intptr_t kNumTemps = 0; |
| 4091 LocationSummary* summary = new (zone) | 3945 LocationSummary* summary = new (zone) |
| 4092 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3946 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4093 summary->set_in(0, Location::RequiresFpuRegister()); | 3947 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4094 summary->set_out(0, Location::RequiresRegister()); | 3948 summary->set_out(0, Location::RequiresRegister()); |
| 4095 return summary; | 3949 return summary; |
| 4096 } | 3950 } |
| 4097 | 3951 |
| 4098 | |
| 4099 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3952 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4100 XmmRegister value = locs()->in(0).fpu_reg(); | 3953 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4101 Register out = locs()->out(0).reg(); | 3954 Register out = locs()->out(0).reg(); |
| 4102 | 3955 |
| 4103 __ movmskps(out, value); | 3956 __ movmskps(out, value); |
| 4104 __ SmiTag(out); | 3957 __ SmiTag(out); |
| 4105 } | 3958 } |
| 4106 | 3959 |
| 4107 | |
| 4108 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3960 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 4109 Zone* zone, | 3961 Zone* zone, |
| 4110 bool opt) const { | 3962 bool opt) const { |
| 4111 const intptr_t kNumInputs = 4; | 3963 const intptr_t kNumInputs = 4; |
| 4112 const intptr_t kNumTemps = 0; | 3964 const intptr_t kNumTemps = 0; |
| 4113 LocationSummary* summary = new (zone) | 3965 LocationSummary* summary = new (zone) |
| 4114 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3966 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4115 summary->set_in(0, Location::RequiresFpuRegister()); | 3967 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4116 summary->set_in(1, Location::RequiresFpuRegister()); | 3968 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4117 summary->set_in(2, Location::RequiresFpuRegister()); | 3969 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4118 summary->set_in(3, Location::RequiresFpuRegister()); | 3970 summary->set_in(3, Location::RequiresFpuRegister()); |
| 4119 summary->set_out(0, Location::SameAsFirstInput()); | 3971 summary->set_out(0, Location::SameAsFirstInput()); |
| 4120 return summary; | 3972 return summary; |
| 4121 } | 3973 } |
| 4122 | 3974 |
| 4123 | |
| 4124 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3975 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4125 XmmRegister v0 = locs()->in(0).fpu_reg(); | 3976 XmmRegister v0 = locs()->in(0).fpu_reg(); |
| 4126 XmmRegister v1 = locs()->in(1).fpu_reg(); | 3977 XmmRegister v1 = locs()->in(1).fpu_reg(); |
| 4127 XmmRegister v2 = locs()->in(2).fpu_reg(); | 3978 XmmRegister v2 = locs()->in(2).fpu_reg(); |
| 4128 XmmRegister v3 = locs()->in(3).fpu_reg(); | 3979 XmmRegister v3 = locs()->in(3).fpu_reg(); |
| 4129 ASSERT(v0 == locs()->out(0).fpu_reg()); | 3980 ASSERT(v0 == locs()->out(0).fpu_reg()); |
| 4130 __ subl(ESP, Immediate(16)); | 3981 __ subl(ESP, Immediate(16)); |
| 4131 __ cvtsd2ss(v0, v0); | 3982 __ cvtsd2ss(v0, v0); |
| 4132 __ movss(Address(ESP, 0), v0); | 3983 __ movss(Address(ESP, 0), v0); |
| 4133 __ movsd(v0, v1); | 3984 __ movsd(v0, v1); |
| 4134 __ cvtsd2ss(v0, v0); | 3985 __ cvtsd2ss(v0, v0); |
| 4135 __ movss(Address(ESP, 4), v0); | 3986 __ movss(Address(ESP, 4), v0); |
| 4136 __ movsd(v0, v2); | 3987 __ movsd(v0, v2); |
| 4137 __ cvtsd2ss(v0, v0); | 3988 __ cvtsd2ss(v0, v0); |
| 4138 __ movss(Address(ESP, 8), v0); | 3989 __ movss(Address(ESP, 8), v0); |
| 4139 __ movsd(v0, v3); | 3990 __ movsd(v0, v3); |
| 4140 __ cvtsd2ss(v0, v0); | 3991 __ cvtsd2ss(v0, v0); |
| 4141 __ movss(Address(ESP, 12), v0); | 3992 __ movss(Address(ESP, 12), v0); |
| 4142 __ movups(v0, Address(ESP, 0)); | 3993 __ movups(v0, Address(ESP, 0)); |
| 4143 __ addl(ESP, Immediate(16)); | 3994 __ addl(ESP, Immediate(16)); |
| 4144 } | 3995 } |
| 4145 | 3996 |
| 4146 | |
| 4147 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 3997 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4148 bool opt) const { | 3998 bool opt) const { |
| 4149 const intptr_t kNumInputs = 0; | 3999 const intptr_t kNumInputs = 0; |
| 4150 const intptr_t kNumTemps = 0; | 4000 const intptr_t kNumTemps = 0; |
| 4151 LocationSummary* summary = new (zone) | 4001 LocationSummary* summary = new (zone) |
| 4152 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4002 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4153 summary->set_out(0, Location::RequiresFpuRegister()); | 4003 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4154 return summary; | 4004 return summary; |
| 4155 } | 4005 } |
| 4156 | 4006 |
| 4157 | |
| 4158 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4007 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4159 XmmRegister value = locs()->out(0).fpu_reg(); | 4008 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4160 __ xorps(value, value); | 4009 __ xorps(value, value); |
| 4161 } | 4010 } |
| 4162 | 4011 |
| 4163 | |
| 4164 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 4012 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
| 4165 bool opt) const { | 4013 bool opt) const { |
| 4166 const intptr_t kNumInputs = 1; | 4014 const intptr_t kNumInputs = 1; |
| 4167 const intptr_t kNumTemps = 0; | 4015 const intptr_t kNumTemps = 0; |
| 4168 LocationSummary* summary = new (zone) | 4016 LocationSummary* summary = new (zone) |
| 4169 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4017 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4170 summary->set_in(0, Location::RequiresFpuRegister()); | 4018 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4171 summary->set_out(0, Location::SameAsFirstInput()); | 4019 summary->set_out(0, Location::SameAsFirstInput()); |
| 4172 return summary; | 4020 return summary; |
| 4173 } | 4021 } |
| 4174 | 4022 |
| 4175 | |
| 4176 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4023 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4177 XmmRegister value = locs()->out(0).fpu_reg(); | 4024 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4178 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); | 4025 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); |
| 4179 // Convert to Float32. | 4026 // Convert to Float32. |
| 4180 __ cvtsd2ss(value, value); | 4027 __ cvtsd2ss(value, value); |
| 4181 // Splat across all lanes. | 4028 // Splat across all lanes. |
| 4182 __ shufps(value, value, Immediate(0x00)); | 4029 __ shufps(value, value, Immediate(0x00)); |
| 4183 } | 4030 } |
| 4184 | 4031 |
| 4185 | |
| 4186 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 4032 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
| 4187 bool opt) const { | 4033 bool opt) const { |
| 4188 const intptr_t kNumInputs = 2; | 4034 const intptr_t kNumInputs = 2; |
| 4189 const intptr_t kNumTemps = 0; | 4035 const intptr_t kNumTemps = 0; |
| 4190 LocationSummary* summary = new (zone) | 4036 LocationSummary* summary = new (zone) |
| 4191 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4037 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4192 summary->set_in(0, Location::RequiresFpuRegister()); | 4038 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4193 summary->set_in(1, Location::RequiresFpuRegister()); | 4039 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4194 summary->set_out(0, Location::SameAsFirstInput()); | 4040 summary->set_out(0, Location::SameAsFirstInput()); |
| 4195 return summary; | 4041 return summary; |
| 4196 } | 4042 } |
| 4197 | 4043 |
| 4198 | |
| 4199 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4044 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4200 XmmRegister left = locs()->in(0).fpu_reg(); | 4045 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4201 XmmRegister right = locs()->in(1).fpu_reg(); | 4046 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4202 | 4047 |
| 4203 ASSERT(locs()->out(0).fpu_reg() == left); | 4048 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4204 | 4049 |
| 4205 switch (op_kind()) { | 4050 switch (op_kind()) { |
| 4206 case MethodRecognizer::kFloat32x4Equal: | 4051 case MethodRecognizer::kFloat32x4Equal: |
| 4207 __ cmppseq(left, right); | 4052 __ cmppseq(left, right); |
| 4208 break; | 4053 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4220 break; | 4065 break; |
| 4221 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 4066 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
| 4222 __ cmppsle(left, right); | 4067 __ cmppsle(left, right); |
| 4223 break; | 4068 break; |
| 4224 | 4069 |
| 4225 default: | 4070 default: |
| 4226 UNREACHABLE(); | 4071 UNREACHABLE(); |
| 4227 } | 4072 } |
| 4228 } | 4073 } |
| 4229 | 4074 |
| 4230 | |
| 4231 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4075 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
| 4232 bool opt) const { | 4076 bool opt) const { |
| 4233 const intptr_t kNumInputs = 2; | 4077 const intptr_t kNumInputs = 2; |
| 4234 const intptr_t kNumTemps = 0; | 4078 const intptr_t kNumTemps = 0; |
| 4235 LocationSummary* summary = new (zone) | 4079 LocationSummary* summary = new (zone) |
| 4236 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4080 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4237 summary->set_in(0, Location::RequiresFpuRegister()); | 4081 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4238 summary->set_in(1, Location::RequiresFpuRegister()); | 4082 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4239 summary->set_out(0, Location::SameAsFirstInput()); | 4083 summary->set_out(0, Location::SameAsFirstInput()); |
| 4240 return summary; | 4084 return summary; |
| 4241 } | 4085 } |
| 4242 | 4086 |
| 4243 | |
| 4244 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4087 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4245 XmmRegister left = locs()->in(0).fpu_reg(); | 4088 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4246 XmmRegister right = locs()->in(1).fpu_reg(); | 4089 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4247 | 4090 |
| 4248 ASSERT(locs()->out(0).fpu_reg() == left); | 4091 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4249 | 4092 |
| 4250 switch (op_kind()) { | 4093 switch (op_kind()) { |
| 4251 case MethodRecognizer::kFloat32x4Min: | 4094 case MethodRecognizer::kFloat32x4Min: |
| 4252 __ minps(left, right); | 4095 __ minps(left, right); |
| 4253 break; | 4096 break; |
| 4254 case MethodRecognizer::kFloat32x4Max: | 4097 case MethodRecognizer::kFloat32x4Max: |
| 4255 __ maxps(left, right); | 4098 __ maxps(left, right); |
| 4256 break; | 4099 break; |
| 4257 default: | 4100 default: |
| 4258 UNREACHABLE(); | 4101 UNREACHABLE(); |
| 4259 } | 4102 } |
| 4260 } | 4103 } |
| 4261 | 4104 |
| 4262 | |
| 4263 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4105 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
| 4264 bool opt) const { | 4106 bool opt) const { |
| 4265 const intptr_t kNumInputs = 2; | 4107 const intptr_t kNumInputs = 2; |
| 4266 const intptr_t kNumTemps = 0; | 4108 const intptr_t kNumTemps = 0; |
| 4267 LocationSummary* summary = new (zone) | 4109 LocationSummary* summary = new (zone) |
| 4268 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4110 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4269 summary->set_in(0, Location::RequiresFpuRegister()); | 4111 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4270 summary->set_in(1, Location::RequiresFpuRegister()); | 4112 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4271 summary->set_out(0, Location::SameAsFirstInput()); | 4113 summary->set_out(0, Location::SameAsFirstInput()); |
| 4272 return summary; | 4114 return summary; |
| 4273 } | 4115 } |
| 4274 | 4116 |
| 4275 | |
| 4276 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4117 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4277 XmmRegister left = locs()->in(0).fpu_reg(); | 4118 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4278 XmmRegister right = locs()->in(1).fpu_reg(); | 4119 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4279 | 4120 |
| 4280 ASSERT(locs()->out(0).fpu_reg() == left); | 4121 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4281 | 4122 |
| 4282 switch (op_kind()) { | 4123 switch (op_kind()) { |
| 4283 case MethodRecognizer::kFloat32x4Scale: | 4124 case MethodRecognizer::kFloat32x4Scale: |
| 4284 __ cvtsd2ss(left, left); | 4125 __ cvtsd2ss(left, left); |
| 4285 __ shufps(left, left, Immediate(0x00)); | 4126 __ shufps(left, left, Immediate(0x00)); |
| 4286 __ mulps(left, right); | 4127 __ mulps(left, right); |
| 4287 break; | 4128 break; |
| 4288 default: | 4129 default: |
| 4289 UNREACHABLE(); | 4130 UNREACHABLE(); |
| 4290 } | 4131 } |
| 4291 } | 4132 } |
| 4292 | 4133 |
| 4293 | |
| 4294 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4134 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
| 4295 bool opt) const { | 4135 bool opt) const { |
| 4296 const intptr_t kNumInputs = 1; | 4136 const intptr_t kNumInputs = 1; |
| 4297 const intptr_t kNumTemps = 0; | 4137 const intptr_t kNumTemps = 0; |
| 4298 LocationSummary* summary = new (zone) | 4138 LocationSummary* summary = new (zone) |
| 4299 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4139 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4300 summary->set_in(0, Location::RequiresFpuRegister()); | 4140 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4301 summary->set_out(0, Location::SameAsFirstInput()); | 4141 summary->set_out(0, Location::SameAsFirstInput()); |
| 4302 return summary; | 4142 return summary; |
| 4303 } | 4143 } |
| 4304 | 4144 |
| 4305 | |
| 4306 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4145 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4307 XmmRegister left = locs()->in(0).fpu_reg(); | 4146 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4308 | 4147 |
| 4309 ASSERT(locs()->out(0).fpu_reg() == left); | 4148 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4310 | 4149 |
| 4311 switch (op_kind()) { | 4150 switch (op_kind()) { |
| 4312 case MethodRecognizer::kFloat32x4Sqrt: | 4151 case MethodRecognizer::kFloat32x4Sqrt: |
| 4313 __ sqrtps(left); | 4152 __ sqrtps(left); |
| 4314 break; | 4153 break; |
| 4315 case MethodRecognizer::kFloat32x4Reciprocal: | 4154 case MethodRecognizer::kFloat32x4Reciprocal: |
| 4316 __ reciprocalps(left); | 4155 __ reciprocalps(left); |
| 4317 break; | 4156 break; |
| 4318 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4157 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 4319 __ rsqrtps(left); | 4158 __ rsqrtps(left); |
| 4320 break; | 4159 break; |
| 4321 default: | 4160 default: |
| 4322 UNREACHABLE(); | 4161 UNREACHABLE(); |
| 4323 } | 4162 } |
| 4324 } | 4163 } |
| 4325 | 4164 |
| 4326 | |
| 4327 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4165 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4328 bool opt) const { | 4166 bool opt) const { |
| 4329 const intptr_t kNumInputs = 1; | 4167 const intptr_t kNumInputs = 1; |
| 4330 const intptr_t kNumTemps = 0; | 4168 const intptr_t kNumTemps = 0; |
| 4331 LocationSummary* summary = new (zone) | 4169 LocationSummary* summary = new (zone) |
| 4332 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4170 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4333 summary->set_in(0, Location::RequiresFpuRegister()); | 4171 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4334 summary->set_out(0, Location::SameAsFirstInput()); | 4172 summary->set_out(0, Location::SameAsFirstInput()); |
| 4335 return summary; | 4173 return summary; |
| 4336 } | 4174 } |
| 4337 | 4175 |
| 4338 | |
| 4339 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4176 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4340 XmmRegister left = locs()->in(0).fpu_reg(); | 4177 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4341 | 4178 |
| 4342 ASSERT(locs()->out(0).fpu_reg() == left); | 4179 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4343 switch (op_kind()) { | 4180 switch (op_kind()) { |
| 4344 case MethodRecognizer::kFloat32x4Negate: | 4181 case MethodRecognizer::kFloat32x4Negate: |
| 4345 __ negateps(left); | 4182 __ negateps(left); |
| 4346 break; | 4183 break; |
| 4347 case MethodRecognizer::kFloat32x4Absolute: | 4184 case MethodRecognizer::kFloat32x4Absolute: |
| 4348 __ absps(left); | 4185 __ absps(left); |
| 4349 break; | 4186 break; |
| 4350 default: | 4187 default: |
| 4351 UNREACHABLE(); | 4188 UNREACHABLE(); |
| 4352 } | 4189 } |
| 4353 } | 4190 } |
| 4354 | 4191 |
| 4355 | |
| 4356 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4192 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
| 4357 bool opt) const { | 4193 bool opt) const { |
| 4358 const intptr_t kNumInputs = 3; | 4194 const intptr_t kNumInputs = 3; |
| 4359 const intptr_t kNumTemps = 0; | 4195 const intptr_t kNumTemps = 0; |
| 4360 LocationSummary* summary = new (zone) | 4196 LocationSummary* summary = new (zone) |
| 4361 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4197 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4362 summary->set_in(0, Location::RequiresFpuRegister()); | 4198 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4363 summary->set_in(1, Location::RequiresFpuRegister()); | 4199 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4364 summary->set_in(2, Location::RequiresFpuRegister()); | 4200 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4365 summary->set_out(0, Location::SameAsFirstInput()); | 4201 summary->set_out(0, Location::SameAsFirstInput()); |
| 4366 return summary; | 4202 return summary; |
| 4367 } | 4203 } |
| 4368 | 4204 |
| 4369 | |
| 4370 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4205 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4371 XmmRegister left = locs()->in(0).fpu_reg(); | 4206 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4372 XmmRegister lower = locs()->in(1).fpu_reg(); | 4207 XmmRegister lower = locs()->in(1).fpu_reg(); |
| 4373 XmmRegister upper = locs()->in(2).fpu_reg(); | 4208 XmmRegister upper = locs()->in(2).fpu_reg(); |
| 4374 ASSERT(locs()->out(0).fpu_reg() == left); | 4209 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4375 __ minps(left, upper); | 4210 __ minps(left, upper); |
| 4376 __ maxps(left, lower); | 4211 __ maxps(left, lower); |
| 4377 } | 4212 } |
| 4378 | 4213 |
| 4379 | |
| 4380 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4214 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
| 4381 bool opt) const { | 4215 bool opt) const { |
| 4382 const intptr_t kNumInputs = 2; | 4216 const intptr_t kNumInputs = 2; |
| 4383 const intptr_t kNumTemps = 0; | 4217 const intptr_t kNumTemps = 0; |
| 4384 LocationSummary* summary = new (zone) | 4218 LocationSummary* summary = new (zone) |
| 4385 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4219 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4386 summary->set_in(0, Location::RequiresFpuRegister()); | 4220 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4387 summary->set_in(1, Location::RequiresFpuRegister()); | 4221 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4388 summary->set_out(0, Location::SameAsFirstInput()); | 4222 summary->set_out(0, Location::SameAsFirstInput()); |
| 4389 return summary; | 4223 return summary; |
| 4390 } | 4224 } |
| 4391 | 4225 |
| 4392 | |
| 4393 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4226 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4394 XmmRegister replacement = locs()->in(0).fpu_reg(); | 4227 XmmRegister replacement = locs()->in(0).fpu_reg(); |
| 4395 XmmRegister value = locs()->in(1).fpu_reg(); | 4228 XmmRegister value = locs()->in(1).fpu_reg(); |
| 4396 | 4229 |
| 4397 ASSERT(locs()->out(0).fpu_reg() == replacement); | 4230 ASSERT(locs()->out(0).fpu_reg() == replacement); |
| 4398 | 4231 |
| 4399 switch (op_kind()) { | 4232 switch (op_kind()) { |
| 4400 case MethodRecognizer::kFloat32x4WithX: | 4233 case MethodRecognizer::kFloat32x4WithX: |
| 4401 __ cvtsd2ss(replacement, replacement); | 4234 __ cvtsd2ss(replacement, replacement); |
| 4402 __ subl(ESP, Immediate(16)); | 4235 __ subl(ESP, Immediate(16)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4439 __ movss(Address(ESP, 12), replacement); | 4272 __ movss(Address(ESP, 12), replacement); |
| 4440 // Move updated value into output register. | 4273 // Move updated value into output register. |
| 4441 __ movups(replacement, Address(ESP, 0)); | 4274 __ movups(replacement, Address(ESP, 0)); |
| 4442 __ addl(ESP, Immediate(16)); | 4275 __ addl(ESP, Immediate(16)); |
| 4443 break; | 4276 break; |
| 4444 default: | 4277 default: |
| 4445 UNREACHABLE(); | 4278 UNREACHABLE(); |
| 4446 } | 4279 } |
| 4447 } | 4280 } |
| 4448 | 4281 |
| 4449 | |
| 4450 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4282 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
| 4451 bool opt) const { | 4283 bool opt) const { |
| 4452 const intptr_t kNumInputs = 1; | 4284 const intptr_t kNumInputs = 1; |
| 4453 const intptr_t kNumTemps = 0; | 4285 const intptr_t kNumTemps = 0; |
| 4454 LocationSummary* summary = new (zone) | 4286 LocationSummary* summary = new (zone) |
| 4455 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4287 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4456 summary->set_in(0, Location::RequiresFpuRegister()); | 4288 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4457 summary->set_out(0, Location::SameAsFirstInput()); | 4289 summary->set_out(0, Location::SameAsFirstInput()); |
| 4458 return summary; | 4290 return summary; |
| 4459 } | 4291 } |
| 4460 | 4292 |
| 4461 | |
| 4462 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4293 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4463 // NOP. | 4294 // NOP. |
| 4464 } | 4295 } |
| 4465 | 4296 |
| 4466 | |
| 4467 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4297 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 4468 bool opt) const { | 4298 bool opt) const { |
| 4469 const intptr_t kNumInputs = 1; | 4299 const intptr_t kNumInputs = 1; |
| 4470 const intptr_t kNumTemps = 0; | 4300 const intptr_t kNumTemps = 0; |
| 4471 LocationSummary* summary = new (zone) | 4301 LocationSummary* summary = new (zone) |
| 4472 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4302 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4473 summary->set_in(0, Location::RequiresFpuRegister()); | 4303 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4474 summary->set_out(0, Location::SameAsFirstInput()); | 4304 summary->set_out(0, Location::SameAsFirstInput()); |
| 4475 return summary; | 4305 return summary; |
| 4476 } | 4306 } |
| 4477 | 4307 |
| 4478 | |
| 4479 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4308 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4480 XmmRegister value = locs()->in(0).fpu_reg(); | 4309 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4481 | 4310 |
| 4482 ASSERT(locs()->out(0).fpu_reg() == value); | 4311 ASSERT(locs()->out(0).fpu_reg() == value); |
| 4483 | 4312 |
| 4484 switch (op_kind()) { | 4313 switch (op_kind()) { |
| 4485 case MethodRecognizer::kFloat64x2GetX: | 4314 case MethodRecognizer::kFloat64x2GetX: |
| 4486 // nop. | 4315 // nop. |
| 4487 break; | 4316 break; |
| 4488 case MethodRecognizer::kFloat64x2GetY: | 4317 case MethodRecognizer::kFloat64x2GetY: |
| 4489 __ shufpd(value, value, Immediate(0x33)); | 4318 __ shufpd(value, value, Immediate(0x33)); |
| 4490 break; | 4319 break; |
| 4491 default: | 4320 default: |
| 4492 UNREACHABLE(); | 4321 UNREACHABLE(); |
| 4493 } | 4322 } |
| 4494 } | 4323 } |
| 4495 | 4324 |
| 4496 | |
| 4497 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4325 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4498 bool opt) const { | 4326 bool opt) const { |
| 4499 const intptr_t kNumInputs = 0; | 4327 const intptr_t kNumInputs = 0; |
| 4500 const intptr_t kNumTemps = 0; | 4328 const intptr_t kNumTemps = 0; |
| 4501 LocationSummary* summary = new (zone) | 4329 LocationSummary* summary = new (zone) |
| 4502 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4330 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4503 summary->set_out(0, Location::RequiresFpuRegister()); | 4331 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4504 return summary; | 4332 return summary; |
| 4505 } | 4333 } |
| 4506 | 4334 |
| 4507 | |
| 4508 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4335 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4509 XmmRegister value = locs()->out(0).fpu_reg(); | 4336 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4510 __ xorpd(value, value); | 4337 __ xorpd(value, value); |
| 4511 } | 4338 } |
| 4512 | 4339 |
| 4513 | |
| 4514 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4340 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
| 4515 bool opt) const { | 4341 bool opt) const { |
| 4516 const intptr_t kNumInputs = 1; | 4342 const intptr_t kNumInputs = 1; |
| 4517 const intptr_t kNumTemps = 0; | 4343 const intptr_t kNumTemps = 0; |
| 4518 LocationSummary* summary = new (zone) | 4344 LocationSummary* summary = new (zone) |
| 4519 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4345 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4520 summary->set_in(0, Location::RequiresFpuRegister()); | 4346 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4521 summary->set_out(0, Location::SameAsFirstInput()); | 4347 summary->set_out(0, Location::SameAsFirstInput()); |
| 4522 return summary; | 4348 return summary; |
| 4523 } | 4349 } |
| 4524 | 4350 |
| 4525 | |
| 4526 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4351 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4527 XmmRegister value = locs()->out(0).fpu_reg(); | 4352 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4528 __ shufpd(value, value, Immediate(0x0)); | 4353 __ shufpd(value, value, Immediate(0x0)); |
| 4529 } | 4354 } |
| 4530 | 4355 |
| 4531 | |
| 4532 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4356 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
| 4533 Zone* zone, | 4357 Zone* zone, |
| 4534 bool opt) const { | 4358 bool opt) const { |
| 4535 const intptr_t kNumInputs = 2; | 4359 const intptr_t kNumInputs = 2; |
| 4536 const intptr_t kNumTemps = 0; | 4360 const intptr_t kNumTemps = 0; |
| 4537 LocationSummary* summary = new (zone) | 4361 LocationSummary* summary = new (zone) |
| 4538 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4362 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4539 summary->set_in(0, Location::RequiresFpuRegister()); | 4363 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4540 summary->set_in(1, Location::RequiresFpuRegister()); | 4364 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4541 summary->set_out(0, Location::SameAsFirstInput()); | 4365 summary->set_out(0, Location::SameAsFirstInput()); |
| 4542 return summary; | 4366 return summary; |
| 4543 } | 4367 } |
| 4544 | 4368 |
| 4545 | |
| 4546 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4369 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4547 XmmRegister v0 = locs()->in(0).fpu_reg(); | 4370 XmmRegister v0 = locs()->in(0).fpu_reg(); |
| 4548 XmmRegister v1 = locs()->in(1).fpu_reg(); | 4371 XmmRegister v1 = locs()->in(1).fpu_reg(); |
| 4549 ASSERT(v0 == locs()->out(0).fpu_reg()); | 4372 ASSERT(v0 == locs()->out(0).fpu_reg()); |
| 4550 // shufpd mask 0x0 results in: | 4373 // shufpd mask 0x0 results in: |
| 4551 // Lower 64-bits of v0 = Lower 64-bits of v0. | 4374 // Lower 64-bits of v0 = Lower 64-bits of v0. |
| 4552 // Upper 64-bits of v0 = Lower 64-bits of v1. | 4375 // Upper 64-bits of v0 = Lower 64-bits of v1. |
| 4553 __ shufpd(v0, v1, Immediate(0x0)); | 4376 __ shufpd(v0, v1, Immediate(0x0)); |
| 4554 } | 4377 } |
| 4555 | 4378 |
| 4556 | |
| 4557 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4379 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
| 4558 Zone* zone, | 4380 Zone* zone, |
| 4559 bool opt) const { | 4381 bool opt) const { |
| 4560 const intptr_t kNumInputs = 1; | 4382 const intptr_t kNumInputs = 1; |
| 4561 const intptr_t kNumTemps = 0; | 4383 const intptr_t kNumTemps = 0; |
| 4562 LocationSummary* summary = new (zone) | 4384 LocationSummary* summary = new (zone) |
| 4563 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4385 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4564 summary->set_in(0, Location::RequiresFpuRegister()); | 4386 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4565 summary->set_out(0, Location::SameAsFirstInput()); | 4387 summary->set_out(0, Location::SameAsFirstInput()); |
| 4566 return summary; | 4388 return summary; |
| 4567 } | 4389 } |
| 4568 | 4390 |
| 4569 | |
| 4570 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4391 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4571 XmmRegister value = locs()->out(0).fpu_reg(); | 4392 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4572 __ cvtpd2ps(value, value); | 4393 __ cvtpd2ps(value, value); |
| 4573 } | 4394 } |
| 4574 | 4395 |
| 4575 | |
| 4576 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4396 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
| 4577 Zone* zone, | 4397 Zone* zone, |
| 4578 bool opt) const { | 4398 bool opt) const { |
| 4579 const intptr_t kNumInputs = 1; | 4399 const intptr_t kNumInputs = 1; |
| 4580 const intptr_t kNumTemps = 0; | 4400 const intptr_t kNumTemps = 0; |
| 4581 LocationSummary* summary = new (zone) | 4401 LocationSummary* summary = new (zone) |
| 4582 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4402 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4583 summary->set_in(0, Location::RequiresFpuRegister()); | 4403 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4584 summary->set_out(0, Location::SameAsFirstInput()); | 4404 summary->set_out(0, Location::SameAsFirstInput()); |
| 4585 return summary; | 4405 return summary; |
| 4586 } | 4406 } |
| 4587 | 4407 |
| 4588 | |
| 4589 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4408 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4590 XmmRegister value = locs()->out(0).fpu_reg(); | 4409 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4591 __ cvtps2pd(value, value); | 4410 __ cvtps2pd(value, value); |
| 4592 } | 4411 } |
| 4593 | 4412 |
| 4594 | |
| 4595 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4413 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4596 bool opt) const { | 4414 bool opt) const { |
| 4597 const intptr_t kNumInputs = 1; | 4415 const intptr_t kNumInputs = 1; |
| 4598 const intptr_t kNumTemps = 0; | 4416 const intptr_t kNumTemps = 0; |
| 4599 LocationSummary* summary = new (zone) | 4417 LocationSummary* summary = new (zone) |
| 4600 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4418 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4601 summary->set_in(0, Location::RequiresFpuRegister()); | 4419 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4602 if (representation() == kTagged) { | 4420 if (representation() == kTagged) { |
| 4603 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4421 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
| 4604 summary->set_out(0, Location::RequiresRegister()); | 4422 summary->set_out(0, Location::RequiresRegister()); |
| 4605 } else { | 4423 } else { |
| 4606 ASSERT(representation() == kUnboxedFloat64x2); | 4424 ASSERT(representation() == kUnboxedFloat64x2); |
| 4607 summary->set_out(0, Location::SameAsFirstInput()); | 4425 summary->set_out(0, Location::SameAsFirstInput()); |
| 4608 } | 4426 } |
| 4609 return summary; | 4427 return summary; |
| 4610 } | 4428 } |
| 4611 | 4429 |
| 4612 | |
| 4613 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4430 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4614 XmmRegister left = locs()->in(0).fpu_reg(); | 4431 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4615 | 4432 |
| 4616 ASSERT((op_kind() == MethodRecognizer::kFloat64x2GetSignMask) || | 4433 ASSERT((op_kind() == MethodRecognizer::kFloat64x2GetSignMask) || |
| 4617 (locs()->out(0).fpu_reg() == left)); | 4434 (locs()->out(0).fpu_reg() == left)); |
| 4618 | 4435 |
| 4619 switch (op_kind()) { | 4436 switch (op_kind()) { |
| 4620 case MethodRecognizer::kFloat64x2Negate: | 4437 case MethodRecognizer::kFloat64x2Negate: |
| 4621 __ negatepd(left); | 4438 __ negatepd(left); |
| 4622 break; | 4439 break; |
| 4623 case MethodRecognizer::kFloat64x2Abs: | 4440 case MethodRecognizer::kFloat64x2Abs: |
| 4624 __ abspd(left); | 4441 __ abspd(left); |
| 4625 break; | 4442 break; |
| 4626 case MethodRecognizer::kFloat64x2Sqrt: | 4443 case MethodRecognizer::kFloat64x2Sqrt: |
| 4627 __ sqrtpd(left); | 4444 __ sqrtpd(left); |
| 4628 break; | 4445 break; |
| 4629 case MethodRecognizer::kFloat64x2GetSignMask: | 4446 case MethodRecognizer::kFloat64x2GetSignMask: |
| 4630 __ movmskpd(locs()->out(0).reg(), left); | 4447 __ movmskpd(locs()->out(0).reg(), left); |
| 4631 __ SmiTag(locs()->out(0).reg()); | 4448 __ SmiTag(locs()->out(0).reg()); |
| 4632 break; | 4449 break; |
| 4633 default: | 4450 default: |
| 4634 UNREACHABLE(); | 4451 UNREACHABLE(); |
| 4635 } | 4452 } |
| 4636 } | 4453 } |
| 4637 | 4454 |
| 4638 | |
| 4639 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 4455 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
| 4640 bool opt) const { | 4456 bool opt) const { |
| 4641 const intptr_t kNumInputs = 2; | 4457 const intptr_t kNumInputs = 2; |
| 4642 const intptr_t kNumTemps = 0; | 4458 const intptr_t kNumTemps = 0; |
| 4643 LocationSummary* summary = new (zone) | 4459 LocationSummary* summary = new (zone) |
| 4644 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4460 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4645 summary->set_in(0, Location::RequiresFpuRegister()); | 4461 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4646 summary->set_in(1, Location::RequiresFpuRegister()); | 4462 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4647 summary->set_out(0, Location::SameAsFirstInput()); | 4463 summary->set_out(0, Location::SameAsFirstInput()); |
| 4648 return summary; | 4464 return summary; |
| 4649 } | 4465 } |
| 4650 | 4466 |
| 4651 | |
| 4652 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4467 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4653 XmmRegister left = locs()->in(0).fpu_reg(); | 4468 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4654 XmmRegister right = locs()->in(1).fpu_reg(); | 4469 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4655 ASSERT((locs()->out(0).fpu_reg() == left)); | 4470 ASSERT((locs()->out(0).fpu_reg() == left)); |
| 4656 | 4471 |
| 4657 switch (op_kind()) { | 4472 switch (op_kind()) { |
| 4658 case MethodRecognizer::kFloat64x2Scale: | 4473 case MethodRecognizer::kFloat64x2Scale: |
| 4659 __ shufpd(right, right, Immediate(0x00)); | 4474 __ shufpd(right, right, Immediate(0x00)); |
| 4660 __ mulpd(left, right); | 4475 __ mulpd(left, right); |
| 4661 break; | 4476 break; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4683 __ minpd(left, right); | 4498 __ minpd(left, right); |
| 4684 break; | 4499 break; |
| 4685 case MethodRecognizer::kFloat64x2Max: | 4500 case MethodRecognizer::kFloat64x2Max: |
| 4686 __ maxpd(left, right); | 4501 __ maxpd(left, right); |
| 4687 break; | 4502 break; |
| 4688 default: | 4503 default: |
| 4689 UNREACHABLE(); | 4504 UNREACHABLE(); |
| 4690 } | 4505 } |
| 4691 } | 4506 } |
| 4692 | 4507 |
| 4693 | |
| 4694 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, | 4508 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
| 4695 bool opt) const { | 4509 bool opt) const { |
| 4696 const intptr_t kNumInputs = 4; | 4510 const intptr_t kNumInputs = 4; |
| 4697 const intptr_t kNumTemps = 0; | 4511 const intptr_t kNumTemps = 0; |
| 4698 LocationSummary* summary = new (zone) | 4512 LocationSummary* summary = new (zone) |
| 4699 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4513 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4700 summary->set_in(0, Location::RequiresRegister()); | 4514 summary->set_in(0, Location::RequiresRegister()); |
| 4701 summary->set_in(1, Location::RequiresRegister()); | 4515 summary->set_in(1, Location::RequiresRegister()); |
| 4702 summary->set_in(2, Location::RequiresRegister()); | 4516 summary->set_in(2, Location::RequiresRegister()); |
| 4703 summary->set_in(3, Location::RequiresRegister()); | 4517 summary->set_in(3, Location::RequiresRegister()); |
| 4704 summary->set_out(0, Location::RequiresFpuRegister()); | 4518 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4705 return summary; | 4519 return summary; |
| 4706 } | 4520 } |
| 4707 | 4521 |
| 4708 | |
| 4709 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4522 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4710 Register v0 = locs()->in(0).reg(); | 4523 Register v0 = locs()->in(0).reg(); |
| 4711 Register v1 = locs()->in(1).reg(); | 4524 Register v1 = locs()->in(1).reg(); |
| 4712 Register v2 = locs()->in(2).reg(); | 4525 Register v2 = locs()->in(2).reg(); |
| 4713 Register v3 = locs()->in(3).reg(); | 4526 Register v3 = locs()->in(3).reg(); |
| 4714 XmmRegister result = locs()->out(0).fpu_reg(); | 4527 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4715 __ subl(ESP, Immediate(4 * kInt32Size)); | 4528 __ subl(ESP, Immediate(4 * kInt32Size)); |
| 4716 __ movl(Address(ESP, 0 * kInt32Size), v0); | 4529 __ movl(Address(ESP, 0 * kInt32Size), v0); |
| 4717 __ movl(Address(ESP, 1 * kInt32Size), v1); | 4530 __ movl(Address(ESP, 1 * kInt32Size), v1); |
| 4718 __ movl(Address(ESP, 2 * kInt32Size), v2); | 4531 __ movl(Address(ESP, 2 * kInt32Size), v2); |
| 4719 __ movl(Address(ESP, 3 * kInt32Size), v3); | 4532 __ movl(Address(ESP, 3 * kInt32Size), v3); |
| 4720 __ movups(result, Address(ESP, 0)); | 4533 __ movups(result, Address(ESP, 0)); |
| 4721 __ addl(ESP, Immediate(4 * kInt32Size)); | 4534 __ addl(ESP, Immediate(4 * kInt32Size)); |
| 4722 } | 4535 } |
| 4723 | 4536 |
| 4724 | |
| 4725 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4537 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
| 4726 Zone* zone, | 4538 Zone* zone, |
| 4727 bool opt) const { | 4539 bool opt) const { |
| 4728 const intptr_t kNumInputs = 4; | 4540 const intptr_t kNumInputs = 4; |
| 4729 const intptr_t kNumTemps = 0; | 4541 const intptr_t kNumTemps = 0; |
| 4730 LocationSummary* summary = new (zone) | 4542 LocationSummary* summary = new (zone) |
| 4731 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4543 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4732 summary->set_in(0, Location::RequiresRegister()); | 4544 summary->set_in(0, Location::RequiresRegister()); |
| 4733 summary->set_in(1, Location::RequiresRegister()); | 4545 summary->set_in(1, Location::RequiresRegister()); |
| 4734 summary->set_in(2, Location::RequiresRegister()); | 4546 summary->set_in(2, Location::RequiresRegister()); |
| 4735 summary->set_in(3, Location::RequiresRegister()); | 4547 summary->set_in(3, Location::RequiresRegister()); |
| 4736 summary->set_out(0, Location::RequiresFpuRegister()); | 4548 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4737 return summary; | 4549 return summary; |
| 4738 } | 4550 } |
| 4739 | 4551 |
| 4740 | |
| 4741 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4552 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4742 Register v0 = locs()->in(0).reg(); | 4553 Register v0 = locs()->in(0).reg(); |
| 4743 Register v1 = locs()->in(1).reg(); | 4554 Register v1 = locs()->in(1).reg(); |
| 4744 Register v2 = locs()->in(2).reg(); | 4555 Register v2 = locs()->in(2).reg(); |
| 4745 Register v3 = locs()->in(3).reg(); | 4556 Register v3 = locs()->in(3).reg(); |
| 4746 XmmRegister result = locs()->out(0).fpu_reg(); | 4557 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4747 Label x_false, x_done; | 4558 Label x_false, x_done; |
| 4748 Label y_false, y_done; | 4559 Label y_false, y_done; |
| 4749 Label z_false, z_done; | 4560 Label z_false, z_done; |
| 4750 Label w_false, w_done; | 4561 Label w_false, w_done; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 4778 __ movl(Address(ESP, 12), Immediate(0xFFFFFFFF)); | 4589 __ movl(Address(ESP, 12), Immediate(0xFFFFFFFF)); |
| 4779 __ jmp(&w_done); | 4590 __ jmp(&w_done); |
| 4780 __ Bind(&w_false); | 4591 __ Bind(&w_false); |
| 4781 __ movl(Address(ESP, 12), Immediate(0x0)); | 4592 __ movl(Address(ESP, 12), Immediate(0x0)); |
| 4782 __ Bind(&w_done); | 4593 __ Bind(&w_done); |
| 4783 | 4594 |
| 4784 __ movups(result, Address(ESP, 0)); | 4595 __ movups(result, Address(ESP, 0)); |
| 4785 __ addl(ESP, Immediate(16)); | 4596 __ addl(ESP, Immediate(16)); |
| 4786 } | 4597 } |
| 4787 | 4598 |
| 4788 | |
| 4789 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4599 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4790 bool opt) const { | 4600 bool opt) const { |
| 4791 const intptr_t kNumInputs = 1; | 4601 const intptr_t kNumInputs = 1; |
| 4792 const intptr_t kNumTemps = 0; | 4602 const intptr_t kNumTemps = 0; |
| 4793 LocationSummary* summary = new (zone) | 4603 LocationSummary* summary = new (zone) |
| 4794 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4604 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4795 summary->set_in(0, Location::RequiresFpuRegister()); | 4605 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4796 summary->set_out(0, Location::RequiresRegister()); | 4606 summary->set_out(0, Location::RequiresRegister()); |
| 4797 return summary; | 4607 return summary; |
| 4798 } | 4608 } |
| 4799 | 4609 |
| 4800 | |
| 4801 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4610 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4802 XmmRegister value = locs()->in(0).fpu_reg(); | 4611 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4803 Register result = locs()->out(0).reg(); | 4612 Register result = locs()->out(0).reg(); |
| 4804 Label done; | 4613 Label done; |
| 4805 Label non_zero; | 4614 Label non_zero; |
| 4806 __ subl(ESP, Immediate(16)); | 4615 __ subl(ESP, Immediate(16)); |
| 4807 // Move value to stack. | 4616 // Move value to stack. |
| 4808 __ movups(Address(ESP, 0), value); | 4617 __ movups(Address(ESP, 0), value); |
| 4809 switch (op_kind()) { | 4618 switch (op_kind()) { |
| 4810 case MethodRecognizer::kInt32x4GetFlagX: | 4619 case MethodRecognizer::kInt32x4GetFlagX: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4825 __ addl(ESP, Immediate(16)); | 4634 __ addl(ESP, Immediate(16)); |
| 4826 __ testl(result, result); | 4635 __ testl(result, result); |
| 4827 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); | 4636 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); |
| 4828 __ LoadObject(result, Bool::False()); | 4637 __ LoadObject(result, Bool::False()); |
| 4829 __ jmp(&done); | 4638 __ jmp(&done); |
| 4830 __ Bind(&non_zero); | 4639 __ Bind(&non_zero); |
| 4831 __ LoadObject(result, Bool::True()); | 4640 __ LoadObject(result, Bool::True()); |
| 4832 __ Bind(&done); | 4641 __ Bind(&done); |
| 4833 } | 4642 } |
| 4834 | 4643 |
| 4835 | |
| 4836 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4644 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
| 4837 bool opt) const { | 4645 bool opt) const { |
| 4838 const intptr_t kNumInputs = 3; | 4646 const intptr_t kNumInputs = 3; |
| 4839 const intptr_t kNumTemps = 1; | 4647 const intptr_t kNumTemps = 1; |
| 4840 LocationSummary* summary = new (zone) | 4648 LocationSummary* summary = new (zone) |
| 4841 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4649 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4842 summary->set_in(0, Location::RequiresFpuRegister()); | 4650 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4843 summary->set_in(1, Location::RequiresFpuRegister()); | 4651 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4844 summary->set_in(2, Location::RequiresFpuRegister()); | 4652 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4845 summary->set_temp(0, Location::RequiresFpuRegister()); | 4653 summary->set_temp(0, Location::RequiresFpuRegister()); |
| 4846 summary->set_out(0, Location::SameAsFirstInput()); | 4654 summary->set_out(0, Location::SameAsFirstInput()); |
| 4847 return summary; | 4655 return summary; |
| 4848 } | 4656 } |
| 4849 | 4657 |
| 4850 | |
| 4851 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4658 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4852 XmmRegister mask = locs()->in(0).fpu_reg(); | 4659 XmmRegister mask = locs()->in(0).fpu_reg(); |
| 4853 XmmRegister trueValue = locs()->in(1).fpu_reg(); | 4660 XmmRegister trueValue = locs()->in(1).fpu_reg(); |
| 4854 XmmRegister falseValue = locs()->in(2).fpu_reg(); | 4661 XmmRegister falseValue = locs()->in(2).fpu_reg(); |
| 4855 XmmRegister out = locs()->out(0).fpu_reg(); | 4662 XmmRegister out = locs()->out(0).fpu_reg(); |
| 4856 XmmRegister temp = locs()->temp(0).fpu_reg(); | 4663 XmmRegister temp = locs()->temp(0).fpu_reg(); |
| 4857 ASSERT(out == mask); | 4664 ASSERT(out == mask); |
| 4858 // Copy mask. | 4665 // Copy mask. |
| 4859 __ movaps(temp, mask); | 4666 __ movaps(temp, mask); |
| 4860 // Invert it. | 4667 // Invert it. |
| 4861 __ notps(temp); | 4668 __ notps(temp); |
| 4862 // mask = mask & trueValue. | 4669 // mask = mask & trueValue. |
| 4863 __ andps(mask, trueValue); | 4670 __ andps(mask, trueValue); |
| 4864 // temp = temp & falseValue. | 4671 // temp = temp & falseValue. |
| 4865 __ andps(temp, falseValue); | 4672 __ andps(temp, falseValue); |
| 4866 // out = mask | temp. | 4673 // out = mask | temp. |
| 4867 __ orps(mask, temp); | 4674 __ orps(mask, temp); |
| 4868 } | 4675 } |
| 4869 | 4676 |
| 4870 | |
| 4871 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 4677 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4872 bool opt) const { | 4678 bool opt) const { |
| 4873 const intptr_t kNumInputs = 2; | 4679 const intptr_t kNumInputs = 2; |
| 4874 const intptr_t kNumTemps = 0; | 4680 const intptr_t kNumTemps = 0; |
| 4875 LocationSummary* summary = new (zone) | 4681 LocationSummary* summary = new (zone) |
| 4876 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4682 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4877 summary->set_in(0, Location::RequiresFpuRegister()); | 4683 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4878 summary->set_in(1, Location::RequiresRegister()); | 4684 summary->set_in(1, Location::RequiresRegister()); |
| 4879 summary->set_out(0, Location::SameAsFirstInput()); | 4685 summary->set_out(0, Location::SameAsFirstInput()); |
| 4880 return summary; | 4686 return summary; |
| 4881 } | 4687 } |
| 4882 | 4688 |
| 4883 | |
| 4884 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4689 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4885 XmmRegister mask = locs()->in(0).fpu_reg(); | 4690 XmmRegister mask = locs()->in(0).fpu_reg(); |
| 4886 Register flag = locs()->in(1).reg(); | 4691 Register flag = locs()->in(1).reg(); |
| 4887 ASSERT(mask == locs()->out(0).fpu_reg()); | 4692 ASSERT(mask == locs()->out(0).fpu_reg()); |
| 4888 __ subl(ESP, Immediate(16)); | 4693 __ subl(ESP, Immediate(16)); |
| 4889 // Copy mask to stack. | 4694 // Copy mask to stack. |
| 4890 __ movups(Address(ESP, 0), mask); | 4695 __ movups(Address(ESP, 0), mask); |
| 4891 Label falsePath, exitPath; | 4696 Label falsePath, exitPath; |
| 4892 __ CompareObject(flag, Bool::True()); | 4697 __ CompareObject(flag, Bool::True()); |
| 4893 __ j(NOT_EQUAL, &falsePath); | 4698 __ j(NOT_EQUAL, &falsePath); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 4918 break; | 4723 break; |
| 4919 default: | 4724 default: |
| 4920 UNREACHABLE(); | 4725 UNREACHABLE(); |
| 4921 } | 4726 } |
| 4922 __ Bind(&exitPath); | 4727 __ Bind(&exitPath); |
| 4923 // Copy mask back to register. | 4728 // Copy mask back to register. |
| 4924 __ movups(mask, Address(ESP, 0)); | 4729 __ movups(mask, Address(ESP, 0)); |
| 4925 __ addl(ESP, Immediate(16)); | 4730 __ addl(ESP, Immediate(16)); |
| 4926 } | 4731 } |
| 4927 | 4732 |
| 4928 | |
| 4929 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4733 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
| 4930 bool opt) const { | 4734 bool opt) const { |
| 4931 const intptr_t kNumInputs = 1; | 4735 const intptr_t kNumInputs = 1; |
| 4932 const intptr_t kNumTemps = 0; | 4736 const intptr_t kNumTemps = 0; |
| 4933 LocationSummary* summary = new (zone) | 4737 LocationSummary* summary = new (zone) |
| 4934 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4738 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4935 summary->set_in(0, Location::RequiresFpuRegister()); | 4739 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4936 summary->set_out(0, Location::SameAsFirstInput()); | 4740 summary->set_out(0, Location::SameAsFirstInput()); |
| 4937 return summary; | 4741 return summary; |
| 4938 } | 4742 } |
| 4939 | 4743 |
| 4940 | |
| 4941 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4744 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4942 // NOP. | 4745 // NOP. |
| 4943 } | 4746 } |
| 4944 | 4747 |
| 4945 | |
| 4946 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 4748 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 4947 bool opt) const { | 4749 bool opt) const { |
| 4948 const intptr_t kNumInputs = 2; | 4750 const intptr_t kNumInputs = 2; |
| 4949 const intptr_t kNumTemps = 0; | 4751 const intptr_t kNumTemps = 0; |
| 4950 LocationSummary* summary = new (zone) | 4752 LocationSummary* summary = new (zone) |
| 4951 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4753 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4952 summary->set_in(0, Location::RequiresFpuRegister()); | 4754 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4953 summary->set_in(1, Location::RequiresFpuRegister()); | 4755 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4954 summary->set_out(0, Location::SameAsFirstInput()); | 4756 summary->set_out(0, Location::SameAsFirstInput()); |
| 4955 return summary; | 4757 return summary; |
| 4956 } | 4758 } |
| 4957 | 4759 |
| 4958 | |
| 4959 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4760 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4960 XmmRegister left = locs()->in(0).fpu_reg(); | 4761 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4961 XmmRegister right = locs()->in(1).fpu_reg(); | 4762 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4962 ASSERT(left == locs()->out(0).fpu_reg()); | 4763 ASSERT(left == locs()->out(0).fpu_reg()); |
| 4963 switch (op_kind()) { | 4764 switch (op_kind()) { |
| 4964 case Token::kBIT_AND: { | 4765 case Token::kBIT_AND: { |
| 4965 __ andps(left, right); | 4766 __ andps(left, right); |
| 4966 break; | 4767 break; |
| 4967 } | 4768 } |
| 4968 case Token::kBIT_OR: { | 4769 case Token::kBIT_OR: { |
| 4969 __ orps(left, right); | 4770 __ orps(left, right); |
| 4970 break; | 4771 break; |
| 4971 } | 4772 } |
| 4972 case Token::kBIT_XOR: { | 4773 case Token::kBIT_XOR: { |
| 4973 __ xorps(left, right); | 4774 __ xorps(left, right); |
| 4974 break; | 4775 break; |
| 4975 } | 4776 } |
| 4976 case Token::kADD: | 4777 case Token::kADD: |
| 4977 __ addpl(left, right); | 4778 __ addpl(left, right); |
| 4978 break; | 4779 break; |
| 4979 case Token::kSUB: | 4780 case Token::kSUB: |
| 4980 __ subpl(left, right); | 4781 __ subpl(left, right); |
| 4981 break; | 4782 break; |
| 4982 default: | 4783 default: |
| 4983 UNREACHABLE(); | 4784 UNREACHABLE(); |
| 4984 } | 4785 } |
| 4985 } | 4786 } |
| 4986 | 4787 |
| 4987 | |
| 4988 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4788 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
| 4989 bool opt) const { | 4789 bool opt) const { |
| 4990 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4790 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
| 4991 (kind() == MathUnaryInstr::kDoubleSquare)); | 4791 (kind() == MathUnaryInstr::kDoubleSquare)); |
| 4992 const intptr_t kNumInputs = 1; | 4792 const intptr_t kNumInputs = 1; |
| 4993 const intptr_t kNumTemps = 0; | 4793 const intptr_t kNumTemps = 0; |
| 4994 LocationSummary* summary = new (zone) | 4794 LocationSummary* summary = new (zone) |
| 4995 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4795 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4996 summary->set_in(0, Location::RequiresFpuRegister()); | 4796 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4997 if (kind() == MathUnaryInstr::kDoubleSquare) { | 4797 if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 4998 summary->set_out(0, Location::SameAsFirstInput()); | 4798 summary->set_out(0, Location::SameAsFirstInput()); |
| 4999 } else { | 4799 } else { |
| 5000 summary->set_out(0, Location::RequiresFpuRegister()); | 4800 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5001 } | 4801 } |
| 5002 return summary; | 4802 return summary; |
| 5003 } | 4803 } |
| 5004 | 4804 |
| 5005 | |
| 5006 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4805 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5007 if (kind() == MathUnaryInstr::kSqrt) { | 4806 if (kind() == MathUnaryInstr::kSqrt) { |
| 5008 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 4807 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 5009 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4808 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 5010 XmmRegister value_reg = locs()->in(0).fpu_reg(); | 4809 XmmRegister value_reg = locs()->in(0).fpu_reg(); |
| 5011 __ mulsd(value_reg, value_reg); | 4810 __ mulsd(value_reg, value_reg); |
| 5012 ASSERT(value_reg == locs()->out(0).fpu_reg()); | 4811 ASSERT(value_reg == locs()->out(0).fpu_reg()); |
| 5013 } else { | 4812 } else { |
| 5014 UNREACHABLE(); | 4813 UNREACHABLE(); |
| 5015 } | 4814 } |
| 5016 } | 4815 } |
| 5017 | 4816 |
| 5018 | |
| 5019 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4817 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
| 5020 Zone* zone, | 4818 Zone* zone, |
| 5021 bool opt) const { | 4819 bool opt) const { |
| 5022 const intptr_t kNumTemps = 0; | 4820 const intptr_t kNumTemps = 0; |
| 5023 LocationSummary* summary = new (zone) | 4821 LocationSummary* summary = new (zone) |
| 5024 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4822 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5025 summary->set_in(0, Location::RegisterLocation(EAX)); | 4823 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 5026 summary->set_in(1, Location::RegisterLocation(ECX)); | 4824 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 5027 summary->set_in(2, Location::RegisterLocation(EDX)); | 4825 summary->set_in(2, Location::RegisterLocation(EDX)); |
| 5028 summary->set_in(3, Location::RegisterLocation(EBX)); | 4826 summary->set_in(3, Location::RegisterLocation(EBX)); |
| 5029 summary->set_out(0, Location::RegisterLocation(EAX)); | 4827 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 5030 return summary; | 4828 return summary; |
| 5031 } | 4829 } |
| 5032 | 4830 |
| 5033 | |
| 5034 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 4831 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
| 5035 FlowGraphCompiler* compiler) { | 4832 FlowGraphCompiler* compiler) { |
| 5036 // Save ESP. EDI is chosen because it is callee saved so we do not need to | 4833 // Save ESP. EDI is chosen because it is callee saved so we do not need to |
| 5037 // back it up before calling into the runtime. | 4834 // back it up before calling into the runtime. |
| 5038 static const Register kSavedSPReg = EDI; | 4835 static const Register kSavedSPReg = EDI; |
| 5039 __ movl(kSavedSPReg, ESP); | 4836 __ movl(kSavedSPReg, ESP); |
| 5040 __ ReserveAlignedFrameSpace(kWordSize * TargetFunction().argument_count()); | 4837 __ ReserveAlignedFrameSpace(kWordSize * TargetFunction().argument_count()); |
| 5041 | 4838 |
| 5042 __ movl(Address(ESP, +0 * kWordSize), locs()->in(0).reg()); | 4839 __ movl(Address(ESP, +0 * kWordSize), locs()->in(0).reg()); |
| 5043 __ movl(Address(ESP, +1 * kWordSize), locs()->in(1).reg()); | 4840 __ movl(Address(ESP, +1 * kWordSize), locs()->in(1).reg()); |
| 5044 __ movl(Address(ESP, +2 * kWordSize), locs()->in(2).reg()); | 4841 __ movl(Address(ESP, +2 * kWordSize), locs()->in(2).reg()); |
| 5045 __ movl(Address(ESP, +3 * kWordSize), locs()->in(3).reg()); | 4842 __ movl(Address(ESP, +3 * kWordSize), locs()->in(3).reg()); |
| 5046 | 4843 |
| 5047 // Call the function. | 4844 // Call the function. |
| 5048 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 4845 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
| 5049 | 4846 |
| 5050 // Restore ESP. | 4847 // Restore ESP. |
| 5051 __ movl(ESP, kSavedSPReg); | 4848 __ movl(ESP, kSavedSPReg); |
| 5052 } | 4849 } |
| 5053 | 4850 |
| 5054 | |
| 5055 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 4851 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
| 5056 bool opt) const { | 4852 bool opt) const { |
| 5057 if (result_cid() == kDoubleCid) { | 4853 if (result_cid() == kDoubleCid) { |
| 5058 const intptr_t kNumInputs = 2; | 4854 const intptr_t kNumInputs = 2; |
| 5059 const intptr_t kNumTemps = 1; | 4855 const intptr_t kNumTemps = 1; |
| 5060 LocationSummary* summary = new (zone) | 4856 LocationSummary* summary = new (zone) |
| 5061 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4857 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5062 summary->set_in(0, Location::RequiresFpuRegister()); | 4858 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5063 summary->set_in(1, Location::RequiresFpuRegister()); | 4859 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5064 // Reuse the left register so that code can be made shorter. | 4860 // Reuse the left register so that code can be made shorter. |
| 5065 summary->set_out(0, Location::SameAsFirstInput()); | 4861 summary->set_out(0, Location::SameAsFirstInput()); |
| 5066 summary->set_temp(0, Location::RequiresRegister()); | 4862 summary->set_temp(0, Location::RequiresRegister()); |
| 5067 return summary; | 4863 return summary; |
| 5068 } | 4864 } |
| 5069 | 4865 |
| 5070 ASSERT(result_cid() == kSmiCid); | 4866 ASSERT(result_cid() == kSmiCid); |
| 5071 const intptr_t kNumInputs = 2; | 4867 const intptr_t kNumInputs = 2; |
| 5072 const intptr_t kNumTemps = 0; | 4868 const intptr_t kNumTemps = 0; |
| 5073 LocationSummary* summary = new (zone) | 4869 LocationSummary* summary = new (zone) |
| 5074 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4870 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5075 summary->set_in(0, Location::RequiresRegister()); | 4871 summary->set_in(0, Location::RequiresRegister()); |
| 5076 summary->set_in(1, Location::RequiresRegister()); | 4872 summary->set_in(1, Location::RequiresRegister()); |
| 5077 // Reuse the left register so that code can be made shorter. | 4873 // Reuse the left register so that code can be made shorter. |
| 5078 summary->set_out(0, Location::SameAsFirstInput()); | 4874 summary->set_out(0, Location::SameAsFirstInput()); |
| 5079 return summary; | 4875 return summary; |
| 5080 } | 4876 } |
| 5081 | 4877 |
| 5082 | |
| 5083 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4878 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5084 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4879 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| 5085 (op_kind() == MethodRecognizer::kMathMax)); | 4880 (op_kind() == MethodRecognizer::kMathMax)); |
| 5086 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); | 4881 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); |
| 5087 if (result_cid() == kDoubleCid) { | 4882 if (result_cid() == kDoubleCid) { |
| 5088 Label done, returns_nan, are_equal; | 4883 Label done, returns_nan, are_equal; |
| 5089 XmmRegister left = locs()->in(0).fpu_reg(); | 4884 XmmRegister left = locs()->in(0).fpu_reg(); |
| 5090 XmmRegister right = locs()->in(1).fpu_reg(); | 4885 XmmRegister right = locs()->in(1).fpu_reg(); |
| 5091 XmmRegister result = locs()->out(0).fpu_reg(); | 4886 XmmRegister result = locs()->out(0).fpu_reg(); |
| 5092 Register temp = locs()->temp(0).reg(); | 4887 Register temp = locs()->temp(0).reg(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5133 Register result = locs()->out(0).reg(); | 4928 Register result = locs()->out(0).reg(); |
| 5134 __ cmpl(left, right); | 4929 __ cmpl(left, right); |
| 5135 ASSERT(result == left); | 4930 ASSERT(result == left); |
| 5136 if (is_min) { | 4931 if (is_min) { |
| 5137 __ cmovgel(result, right); | 4932 __ cmovgel(result, right); |
| 5138 } else { | 4933 } else { |
| 5139 __ cmovlessl(result, right); | 4934 __ cmovlessl(result, right); |
| 5140 } | 4935 } |
| 5141 } | 4936 } |
| 5142 | 4937 |
| 5143 | |
| 5144 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 4938 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 5145 bool opt) const { | 4939 bool opt) const { |
| 5146 const intptr_t kNumInputs = 1; | 4940 const intptr_t kNumInputs = 1; |
| 5147 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), | 4941 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
| 5148 LocationSummary::kNoCall); | 4942 LocationSummary::kNoCall); |
| 5149 } | 4943 } |
| 5150 | 4944 |
| 5151 | |
| 5152 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4945 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5153 Register value = locs()->in(0).reg(); | 4946 Register value = locs()->in(0).reg(); |
| 5154 ASSERT(value == locs()->out(0).reg()); | 4947 ASSERT(value == locs()->out(0).reg()); |
| 5155 switch (op_kind()) { | 4948 switch (op_kind()) { |
| 5156 case Token::kNEGATE: { | 4949 case Token::kNEGATE: { |
| 5157 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 4950 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
| 5158 __ negl(value); | 4951 __ negl(value); |
| 5159 __ j(OVERFLOW, deopt); | 4952 __ j(OVERFLOW, deopt); |
| 5160 break; | 4953 break; |
| 5161 } | 4954 } |
| 5162 case Token::kBIT_NOT: | 4955 case Token::kBIT_NOT: |
| 5163 __ notl(value); | 4956 __ notl(value); |
| 5164 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 4957 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
| 5165 break; | 4958 break; |
| 5166 default: | 4959 default: |
| 5167 UNREACHABLE(); | 4960 UNREACHABLE(); |
| 5168 } | 4961 } |
| 5169 } | 4962 } |
| 5170 | 4963 |
| 5171 | |
| 5172 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4964 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 5173 bool opt) const { | 4965 bool opt) const { |
| 5174 const intptr_t kNumInputs = 1; | 4966 const intptr_t kNumInputs = 1; |
| 5175 const intptr_t kNumTemps = 0; | 4967 const intptr_t kNumTemps = 0; |
| 5176 LocationSummary* summary = new (zone) | 4968 LocationSummary* summary = new (zone) |
| 5177 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4969 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5178 summary->set_in(0, Location::RequiresFpuRegister()); | 4970 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5179 summary->set_out(0, Location::SameAsFirstInput()); | 4971 summary->set_out(0, Location::SameAsFirstInput()); |
| 5180 return summary; | 4972 return summary; |
| 5181 } | 4973 } |
| 5182 | 4974 |
| 5183 | |
| 5184 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4975 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5185 XmmRegister value = locs()->in(0).fpu_reg(); | 4976 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5186 ASSERT(locs()->out(0).fpu_reg() == value); | 4977 ASSERT(locs()->out(0).fpu_reg() == value); |
| 5187 __ DoubleNegate(value); | 4978 __ DoubleNegate(value); |
| 5188 } | 4979 } |
| 5189 | 4980 |
| 5190 | |
| 5191 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 4981 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5192 bool opt) const { | 4982 bool opt) const { |
| 5193 const intptr_t kNumInputs = 1; | 4983 const intptr_t kNumInputs = 1; |
| 5194 const intptr_t kNumTemps = 0; | 4984 const intptr_t kNumTemps = 0; |
| 5195 LocationSummary* result = new (zone) | 4985 LocationSummary* result = new (zone) |
| 5196 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4986 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5197 result->set_in(0, Location::RequiresRegister()); | 4987 result->set_in(0, Location::RequiresRegister()); |
| 5198 result->set_out(0, Location::RequiresFpuRegister()); | 4988 result->set_out(0, Location::RequiresFpuRegister()); |
| 5199 return result; | 4989 return result; |
| 5200 } | 4990 } |
| 5201 | 4991 |
| 5202 | |
| 5203 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4992 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5204 Register value = locs()->in(0).reg(); | 4993 Register value = locs()->in(0).reg(); |
| 5205 FpuRegister result = locs()->out(0).fpu_reg(); | 4994 FpuRegister result = locs()->out(0).fpu_reg(); |
| 5206 __ cvtsi2sd(result, value); | 4995 __ cvtsi2sd(result, value); |
| 5207 } | 4996 } |
| 5208 | 4997 |
| 5209 | |
| 5210 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 4998 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5211 bool opt) const { | 4999 bool opt) const { |
| 5212 const intptr_t kNumInputs = 1; | 5000 const intptr_t kNumInputs = 1; |
| 5213 const intptr_t kNumTemps = 0; | 5001 const intptr_t kNumTemps = 0; |
| 5214 LocationSummary* result = new (zone) | 5002 LocationSummary* result = new (zone) |
| 5215 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5003 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5216 result->set_in(0, Location::WritableRegister()); | 5004 result->set_in(0, Location::WritableRegister()); |
| 5217 result->set_out(0, Location::RequiresFpuRegister()); | 5005 result->set_out(0, Location::RequiresFpuRegister()); |
| 5218 return result; | 5006 return result; |
| 5219 } | 5007 } |
| 5220 | 5008 |
| 5221 | |
| 5222 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5009 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5223 Register value = locs()->in(0).reg(); | 5010 Register value = locs()->in(0).reg(); |
| 5224 FpuRegister result = locs()->out(0).fpu_reg(); | 5011 FpuRegister result = locs()->out(0).fpu_reg(); |
| 5225 __ SmiUntag(value); | 5012 __ SmiUntag(value); |
| 5226 __ cvtsi2sd(result, value); | 5013 __ cvtsi2sd(result, value); |
| 5227 } | 5014 } |
| 5228 | 5015 |
| 5229 | |
| 5230 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, | 5016 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5231 bool opt) const { | 5017 bool opt) const { |
| 5232 const intptr_t kNumInputs = 1; | 5018 const intptr_t kNumInputs = 1; |
| 5233 const intptr_t kNumTemps = 0; | 5019 const intptr_t kNumTemps = 0; |
| 5234 LocationSummary* result = new (zone) | 5020 LocationSummary* result = new (zone) |
| 5235 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5021 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5236 result->set_in(0, Location::Pair(Location::RequiresRegister(), | 5022 result->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5237 Location::RequiresRegister())); | 5023 Location::RequiresRegister())); |
| 5238 result->set_out(0, Location::RequiresFpuRegister()); | 5024 result->set_out(0, Location::RequiresFpuRegister()); |
| 5239 return result; | 5025 return result; |
| 5240 } | 5026 } |
| 5241 | 5027 |
| 5242 | |
| 5243 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5028 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5244 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5029 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 5245 Register in_lo = pair->At(0).reg(); | 5030 Register in_lo = pair->At(0).reg(); |
| 5246 Register in_hi = pair->At(1).reg(); | 5031 Register in_hi = pair->At(1).reg(); |
| 5247 | 5032 |
| 5248 FpuRegister result = locs()->out(0).fpu_reg(); | 5033 FpuRegister result = locs()->out(0).fpu_reg(); |
| 5249 | 5034 |
| 5250 // Push hi. | 5035 // Push hi. |
| 5251 __ pushl(in_hi); | 5036 __ pushl(in_hi); |
| 5252 // Push lo. | 5037 // Push lo. |
| 5253 __ pushl(in_lo); | 5038 __ pushl(in_lo); |
| 5254 // Perform conversion from Mint to double. | 5039 // Perform conversion from Mint to double. |
| 5255 __ fildl(Address(ESP, 0)); | 5040 __ fildl(Address(ESP, 0)); |
| 5256 // Pop FPU stack onto regular stack. | 5041 // Pop FPU stack onto regular stack. |
| 5257 __ fstpl(Address(ESP, 0)); | 5042 __ fstpl(Address(ESP, 0)); |
| 5258 // Copy into result. | 5043 // Copy into result. |
| 5259 __ movsd(result, Address(ESP, 0)); | 5044 __ movsd(result, Address(ESP, 0)); |
| 5260 // Pop args. | 5045 // Pop args. |
| 5261 __ addl(ESP, Immediate(2 * kWordSize)); | 5046 __ addl(ESP, Immediate(2 * kWordSize)); |
| 5262 } | 5047 } |
| 5263 | 5048 |
| 5264 | |
| 5265 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 5049 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
| 5266 bool opt) const { | 5050 bool opt) const { |
| 5267 const intptr_t kNumInputs = 1; | 5051 const intptr_t kNumInputs = 1; |
| 5268 const intptr_t kNumTemps = 0; | 5052 const intptr_t kNumTemps = 0; |
| 5269 LocationSummary* result = new (zone) | 5053 LocationSummary* result = new (zone) |
| 5270 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5054 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5271 result->set_in(0, Location::RegisterLocation(ECX)); | 5055 result->set_in(0, Location::RegisterLocation(ECX)); |
| 5272 result->set_out(0, Location::RegisterLocation(EAX)); | 5056 result->set_out(0, Location::RegisterLocation(EAX)); |
| 5273 return result; | 5057 return result; |
| 5274 } | 5058 } |
| 5275 | 5059 |
| 5276 | |
| 5277 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5060 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5278 Register result = locs()->out(0).reg(); | 5061 Register result = locs()->out(0).reg(); |
| 5279 Register value_obj = locs()->in(0).reg(); | 5062 Register value_obj = locs()->in(0).reg(); |
| 5280 XmmRegister value_double = XMM0; | 5063 XmmRegister value_double = XMM0; |
| 5281 ASSERT(result == EAX); | 5064 ASSERT(result == EAX); |
| 5282 ASSERT(result != value_obj); | 5065 ASSERT(result != value_obj); |
| 5283 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); | 5066 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); |
| 5284 __ cvttsd2si(result, value_double); | 5067 __ cvttsd2si(result, value_double); |
| 5285 // Overflow is signalled with minint. | 5068 // Overflow is signalled with minint. |
| 5286 Label do_call, done; | 5069 Label do_call, done; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5297 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 5080 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 5298 const int kTypeArgsLen = 0; | 5081 const int kTypeArgsLen = 0; |
| 5299 const int kNumberOfArguments = 1; | 5082 const int kNumberOfArguments = 1; |
| 5300 const Array& kNoArgumentNames = Object::null_array(); | 5083 const Array& kNoArgumentNames = Object::null_array(); |
| 5301 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); | 5084 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); |
| 5302 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, | 5085 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
| 5303 args_info, locs(), ICData::Handle()); | 5086 args_info, locs(), ICData::Handle()); |
| 5304 __ Bind(&done); | 5087 __ Bind(&done); |
| 5305 } | 5088 } |
| 5306 | 5089 |
| 5307 | |
| 5308 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5090 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
| 5309 bool opt) const { | 5091 bool opt) const { |
| 5310 const intptr_t kNumInputs = 1; | 5092 const intptr_t kNumInputs = 1; |
| 5311 const intptr_t kNumTemps = 0; | 5093 const intptr_t kNumTemps = 0; |
| 5312 LocationSummary* result = new (zone) | 5094 LocationSummary* result = new (zone) |
| 5313 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5095 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5314 result->set_in(0, Location::RequiresFpuRegister()); | 5096 result->set_in(0, Location::RequiresFpuRegister()); |
| 5315 result->set_out(0, Location::RequiresRegister()); | 5097 result->set_out(0, Location::RequiresRegister()); |
| 5316 return result; | 5098 return result; |
| 5317 } | 5099 } |
| 5318 | 5100 |
| 5319 | |
| 5320 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5101 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5321 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5102 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
| 5322 Register result = locs()->out(0).reg(); | 5103 Register result = locs()->out(0).reg(); |
| 5323 XmmRegister value = locs()->in(0).fpu_reg(); | 5104 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5324 __ cvttsd2si(result, value); | 5105 __ cvttsd2si(result, value); |
| 5325 // Check for overflow and that it fits into Smi. | 5106 // Check for overflow and that it fits into Smi. |
| 5326 __ cmpl(result, Immediate(0xC0000000)); | 5107 __ cmpl(result, Immediate(0xC0000000)); |
| 5327 __ j(NEGATIVE, deopt); | 5108 __ j(NEGATIVE, deopt); |
| 5328 __ SmiTag(result); | 5109 __ SmiTag(result); |
| 5329 } | 5110 } |
| 5330 | 5111 |
| 5331 | |
| 5332 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, | 5112 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5333 bool opt) const { | 5113 bool opt) const { |
| 5334 const intptr_t kNumInputs = 1; | 5114 const intptr_t kNumInputs = 1; |
| 5335 const intptr_t kNumTemps = 0; | 5115 const intptr_t kNumTemps = 0; |
| 5336 LocationSummary* result = new (zone) | 5116 LocationSummary* result = new (zone) |
| 5337 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5117 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5338 result->set_in(0, Location::RequiresFpuRegister()); | 5118 result->set_in(0, Location::RequiresFpuRegister()); |
| 5339 result->set_out(0, Location::RequiresFpuRegister()); | 5119 result->set_out(0, Location::RequiresFpuRegister()); |
| 5340 return result; | 5120 return result; |
| 5341 } | 5121 } |
| 5342 | 5122 |
| 5343 | |
| 5344 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5123 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5345 XmmRegister value = locs()->in(0).fpu_reg(); | 5124 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5346 XmmRegister result = locs()->out(0).fpu_reg(); | 5125 XmmRegister result = locs()->out(0).fpu_reg(); |
| 5347 switch (recognized_kind()) { | 5126 switch (recognized_kind()) { |
| 5348 case MethodRecognizer::kDoubleTruncate: | 5127 case MethodRecognizer::kDoubleTruncate: |
| 5349 __ roundsd(result, value, Assembler::kRoundToZero); | 5128 __ roundsd(result, value, Assembler::kRoundToZero); |
| 5350 break; | 5129 break; |
| 5351 case MethodRecognizer::kDoubleFloor: | 5130 case MethodRecognizer::kDoubleFloor: |
| 5352 __ roundsd(result, value, Assembler::kRoundDown); | 5131 __ roundsd(result, value, Assembler::kRoundDown); |
| 5353 break; | 5132 break; |
| 5354 case MethodRecognizer::kDoubleCeil: | 5133 case MethodRecognizer::kDoubleCeil: |
| 5355 __ roundsd(result, value, Assembler::kRoundUp); | 5134 __ roundsd(result, value, Assembler::kRoundUp); |
| 5356 break; | 5135 break; |
| 5357 default: | 5136 default: |
| 5358 UNREACHABLE(); | 5137 UNREACHABLE(); |
| 5359 } | 5138 } |
| 5360 } | 5139 } |
| 5361 | 5140 |
| 5362 | |
| 5363 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5141 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
| 5364 bool opt) const { | 5142 bool opt) const { |
| 5365 const intptr_t kNumInputs = 1; | 5143 const intptr_t kNumInputs = 1; |
| 5366 const intptr_t kNumTemps = 0; | 5144 const intptr_t kNumTemps = 0; |
| 5367 LocationSummary* result = new (zone) | 5145 LocationSummary* result = new (zone) |
| 5368 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5146 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5369 result->set_in(0, Location::RequiresFpuRegister()); | 5147 result->set_in(0, Location::RequiresFpuRegister()); |
| 5370 result->set_out(0, Location::SameAsFirstInput()); | 5148 result->set_out(0, Location::SameAsFirstInput()); |
| 5371 return result; | 5149 return result; |
| 5372 } | 5150 } |
| 5373 | 5151 |
| 5374 | |
| 5375 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5152 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5376 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5153 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 5377 } | 5154 } |
| 5378 | 5155 |
| 5379 | |
| 5380 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5156 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5381 bool opt) const { | 5157 bool opt) const { |
| 5382 const intptr_t kNumInputs = 1; | 5158 const intptr_t kNumInputs = 1; |
| 5383 const intptr_t kNumTemps = 0; | 5159 const intptr_t kNumTemps = 0; |
| 5384 LocationSummary* result = new (zone) | 5160 LocationSummary* result = new (zone) |
| 5385 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5161 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5386 result->set_in(0, Location::RequiresFpuRegister()); | 5162 result->set_in(0, Location::RequiresFpuRegister()); |
| 5387 result->set_out(0, Location::SameAsFirstInput()); | 5163 result->set_out(0, Location::SameAsFirstInput()); |
| 5388 return result; | 5164 return result; |
| 5389 } | 5165 } |
| 5390 | 5166 |
| 5391 | |
| 5392 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5167 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5393 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5168 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 5394 } | 5169 } |
| 5395 | 5170 |
| 5396 | |
| 5397 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5171 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
| 5398 bool opt) const { | 5172 bool opt) const { |
| 5399 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5173 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 5400 const intptr_t kNumTemps = | 5174 const intptr_t kNumTemps = |
| 5401 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; | 5175 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; |
| 5402 LocationSummary* result = new (zone) | 5176 LocationSummary* result = new (zone) |
| 5403 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5177 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5404 // EDI is chosen because it is callee saved so we do not need to back it | 5178 // EDI is chosen because it is callee saved so we do not need to back it |
| 5405 // up before calling into the runtime. | 5179 // up before calling into the runtime. |
| 5406 result->set_temp(0, Location::RegisterLocation(EDI)); | 5180 result->set_temp(0, Location::RegisterLocation(EDI)); |
| 5407 result->set_in(0, Location::FpuRegisterLocation(XMM1)); | 5181 result->set_in(0, Location::FpuRegisterLocation(XMM1)); |
| 5408 if (InputCount() == 2) { | 5182 if (InputCount() == 2) { |
| 5409 result->set_in(1, Location::FpuRegisterLocation(XMM2)); | 5183 result->set_in(1, Location::FpuRegisterLocation(XMM2)); |
| 5410 } | 5184 } |
| 5411 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5185 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5412 // Temp index 1. | 5186 // Temp index 1. |
| 5413 result->set_temp(1, Location::RegisterLocation(EAX)); | 5187 result->set_temp(1, Location::RegisterLocation(EAX)); |
| 5414 // Temp index 2. | 5188 // Temp index 2. |
| 5415 result->set_temp(2, Location::FpuRegisterLocation(XMM4)); | 5189 result->set_temp(2, Location::FpuRegisterLocation(XMM4)); |
| 5416 } | 5190 } |
| 5417 result->set_out(0, Location::FpuRegisterLocation(XMM3)); | 5191 result->set_out(0, Location::FpuRegisterLocation(XMM3)); |
| 5418 return result; | 5192 return result; |
| 5419 } | 5193 } |
| 5420 | 5194 |
| 5421 | |
| 5422 // Pseudo code: | 5195 // Pseudo code: |
| 5423 // if (exponent == 0.0) return 1.0; | 5196 // if (exponent == 0.0) return 1.0; |
| 5424 // // Speed up simple cases. | 5197 // // Speed up simple cases. |
| 5425 // if (exponent == 1.0) return base; | 5198 // if (exponent == 1.0) return base; |
| 5426 // if (exponent == 2.0) return base * base; | 5199 // if (exponent == 2.0) return base * base; |
| 5427 // if (exponent == 3.0) return base * base * base; | 5200 // if (exponent == 3.0) return base * base * base; |
| 5428 // if (base == 1.0) return 1.0; | 5201 // if (base == 1.0) return 1.0; |
| 5429 // if (base.isNaN || exponent.isNaN) { | 5202 // if (base.isNaN || exponent.isNaN) { |
| 5430 // return double.NAN; | 5203 // return double.NAN; |
| 5431 // } | 5204 // } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5544 __ movsd(Address(ESP, kDoubleSize * i), locs->in(i).fpu_reg()); | 5317 __ movsd(Address(ESP, kDoubleSize * i), locs->in(i).fpu_reg()); |
| 5545 } | 5318 } |
| 5546 __ CallRuntime(instr->TargetFunction(), kInputCount); | 5319 __ CallRuntime(instr->TargetFunction(), kInputCount); |
| 5547 __ fstpl(Address(ESP, 0)); | 5320 __ fstpl(Address(ESP, 0)); |
| 5548 __ movsd(locs->out(0).fpu_reg(), Address(ESP, 0)); | 5321 __ movsd(locs->out(0).fpu_reg(), Address(ESP, 0)); |
| 5549 // Restore ESP. | 5322 // Restore ESP. |
| 5550 __ movl(ESP, locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg()); | 5323 __ movl(ESP, locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg()); |
| 5551 __ Bind(&skip_call); | 5324 __ Bind(&skip_call); |
| 5552 } | 5325 } |
| 5553 | 5326 |
| 5554 | |
| 5555 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5327 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5556 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5328 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5557 InvokeDoublePow(compiler, this); | 5329 InvokeDoublePow(compiler, this); |
| 5558 return; | 5330 return; |
| 5559 } | 5331 } |
| 5560 // Save ESP. | 5332 // Save ESP. |
| 5561 __ movl(locs()->temp(kSavedSpTempIndex).reg(), ESP); | 5333 __ movl(locs()->temp(kSavedSpTempIndex).reg(), ESP); |
| 5562 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); | 5334 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); |
| 5563 for (intptr_t i = 0; i < InputCount(); i++) { | 5335 for (intptr_t i = 0; i < InputCount(); i++) { |
| 5564 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); | 5336 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); |
| 5565 } | 5337 } |
| 5566 | 5338 |
| 5567 __ CallRuntime(TargetFunction(), InputCount()); | 5339 __ CallRuntime(TargetFunction(), InputCount()); |
| 5568 __ fstpl(Address(ESP, 0)); | 5340 __ fstpl(Address(ESP, 0)); |
| 5569 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); | 5341 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); |
| 5570 // Restore ESP. | 5342 // Restore ESP. |
| 5571 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); | 5343 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); |
| 5572 } | 5344 } |
| 5573 | 5345 |
| 5574 | |
| 5575 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 5346 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
| 5576 bool opt) const { | 5347 bool opt) const { |
| 5577 // Only use this instruction in optimized code. | 5348 // Only use this instruction in optimized code. |
| 5578 ASSERT(opt); | 5349 ASSERT(opt); |
| 5579 const intptr_t kNumInputs = 1; | 5350 const intptr_t kNumInputs = 1; |
| 5580 LocationSummary* summary = | 5351 LocationSummary* summary = |
| 5581 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 5352 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 5582 if (representation() == kUnboxedDouble) { | 5353 if (representation() == kUnboxedDouble) { |
| 5583 if (index() == 0) { | 5354 if (index() == 0) { |
| 5584 summary->set_in( | 5355 summary->set_in( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5597 } else { | 5368 } else { |
| 5598 ASSERT(index() == 1); | 5369 ASSERT(index() == 1); |
| 5599 summary->set_in( | 5370 summary->set_in( |
| 5600 0, Location::Pair(Location::Any(), Location::RequiresRegister())); | 5371 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
| 5601 } | 5372 } |
| 5602 summary->set_out(0, Location::RequiresRegister()); | 5373 summary->set_out(0, Location::RequiresRegister()); |
| 5603 } | 5374 } |
| 5604 return summary; | 5375 return summary; |
| 5605 } | 5376 } |
| 5606 | 5377 |
| 5607 | |
| 5608 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5378 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5609 ASSERT(locs()->in(0).IsPairLocation()); | 5379 ASSERT(locs()->in(0).IsPairLocation()); |
| 5610 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5380 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 5611 Location in_loc = pair->At(index()); | 5381 Location in_loc = pair->At(index()); |
| 5612 if (representation() == kUnboxedDouble) { | 5382 if (representation() == kUnboxedDouble) { |
| 5613 XmmRegister out = locs()->out(0).fpu_reg(); | 5383 XmmRegister out = locs()->out(0).fpu_reg(); |
| 5614 XmmRegister in = in_loc.fpu_reg(); | 5384 XmmRegister in = in_loc.fpu_reg(); |
| 5615 __ movaps(out, in); | 5385 __ movaps(out, in); |
| 5616 } else { | 5386 } else { |
| 5617 ASSERT(representation() == kTagged); | 5387 ASSERT(representation() == kTagged); |
| 5618 Register out = locs()->out(0).reg(); | 5388 Register out = locs()->out(0).reg(); |
| 5619 Register in = in_loc.reg(); | 5389 Register in = in_loc.reg(); |
| 5620 __ movl(out, in); | 5390 __ movl(out, in); |
| 5621 } | 5391 } |
| 5622 } | 5392 } |
| 5623 | 5393 |
| 5624 | |
| 5625 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, | 5394 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, |
| 5626 bool opt) const { | 5395 bool opt) const { |
| 5627 const intptr_t kNumInputs = 2; | 5396 const intptr_t kNumInputs = 2; |
| 5628 const intptr_t kNumTemps = 0; | 5397 const intptr_t kNumTemps = 0; |
| 5629 LocationSummary* summary = new (zone) | 5398 LocationSummary* summary = new (zone) |
| 5630 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5399 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5631 // Both inputs must be writable because they will be untagged. | 5400 // Both inputs must be writable because they will be untagged. |
| 5632 summary->set_in(0, Location::RegisterLocation(EAX)); | 5401 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 5633 summary->set_in(1, Location::WritableRegister()); | 5402 summary->set_in(1, Location::WritableRegister()); |
| 5634 // Output is a pair of registers. | 5403 // Output is a pair of registers. |
| 5635 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 5404 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
| 5636 Location::RegisterLocation(EDX))); | 5405 Location::RegisterLocation(EDX))); |
| 5637 return summary; | 5406 return summary; |
| 5638 } | 5407 } |
| 5639 | 5408 |
| 5640 | |
| 5641 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5409 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5642 ASSERT(CanDeoptimize()); | 5410 ASSERT(CanDeoptimize()); |
| 5643 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5411 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
| 5644 Register left = locs()->in(0).reg(); | 5412 Register left = locs()->in(0).reg(); |
| 5645 Register right = locs()->in(1).reg(); | 5413 Register right = locs()->in(1).reg(); |
| 5646 ASSERT(locs()->out(0).IsPairLocation()); | 5414 ASSERT(locs()->out(0).IsPairLocation()); |
| 5647 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5415 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 5648 Register result1 = pair->At(0).reg(); | 5416 Register result1 = pair->At(0).reg(); |
| 5649 Register result2 = pair->At(1).reg(); | 5417 Register result2 = pair->At(1).reg(); |
| 5650 if (RangeUtils::CanBeZero(divisor_range())) { | 5418 if (RangeUtils::CanBeZero(divisor_range())) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5694 } else { | 5462 } else { |
| 5695 // Right is negative. | 5463 // Right is negative. |
| 5696 __ subl(EDX, right); | 5464 __ subl(EDX, right); |
| 5697 } | 5465 } |
| 5698 __ Bind(&done); | 5466 __ Bind(&done); |
| 5699 | 5467 |
| 5700 __ SmiTag(EAX); | 5468 __ SmiTag(EAX); |
| 5701 __ SmiTag(EDX); | 5469 __ SmiTag(EDX); |
| 5702 } | 5470 } |
| 5703 | 5471 |
| 5704 | |
| 5705 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5472 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
| 5706 Zone* zone, | 5473 Zone* zone, |
| 5707 bool opt) const { | 5474 bool opt) const { |
| 5708 return MakeCallSummary(zone); | 5475 return MakeCallSummary(zone); |
| 5709 } | 5476 } |
| 5710 | 5477 |
| 5711 | |
| 5712 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 5478 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5713 comparison()->InitializeLocationSummary(zone, opt); | 5479 comparison()->InitializeLocationSummary(zone, opt); |
| 5714 // Branches don't produce a result. | 5480 // Branches don't produce a result. |
| 5715 comparison()->locs()->set_out(0, Location::NoLocation()); | 5481 comparison()->locs()->set_out(0, Location::NoLocation()); |
| 5716 return comparison()->locs(); | 5482 return comparison()->locs(); |
| 5717 } | 5483 } |
| 5718 | 5484 |
| 5719 | |
| 5720 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5485 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5721 comparison()->EmitBranchCode(compiler, this); | 5486 comparison()->EmitBranchCode(compiler, this); |
| 5722 } | 5487 } |
| 5723 | 5488 |
| 5724 | |
| 5725 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5489 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
| 5726 bool opt) const { | 5490 bool opt) const { |
| 5727 const intptr_t kNumInputs = 1; | 5491 const intptr_t kNumInputs = 1; |
| 5728 const bool need_mask_temp = IsBitTest(); | 5492 const bool need_mask_temp = IsBitTest(); |
| 5729 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5493 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
| 5730 LocationSummary* summary = new (zone) | 5494 LocationSummary* summary = new (zone) |
| 5731 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5495 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5732 summary->set_in(0, Location::RequiresRegister()); | 5496 summary->set_in(0, Location::RequiresRegister()); |
| 5733 if (!IsNullCheck()) { | 5497 if (!IsNullCheck()) { |
| 5734 summary->set_temp(0, Location::RequiresRegister()); | 5498 summary->set_temp(0, Location::RequiresRegister()); |
| 5735 if (need_mask_temp) { | 5499 if (need_mask_temp) { |
| 5736 summary->set_temp(1, Location::RequiresRegister()); | 5500 summary->set_temp(1, Location::RequiresRegister()); |
| 5737 } | 5501 } |
| 5738 } | 5502 } |
| 5739 return summary; | 5503 return summary; |
| 5740 } | 5504 } |
| 5741 | 5505 |
| 5742 | |
| 5743 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { | 5506 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { |
| 5744 const Immediate& raw_null = | 5507 const Immediate& raw_null = |
| 5745 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 5508 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 5746 __ cmpl(locs()->in(0).reg(), raw_null); | 5509 __ cmpl(locs()->in(0).reg(), raw_null); |
| 5747 ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull()); | 5510 ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull()); |
| 5748 Condition cond = IsDeoptIfNull() ? EQUAL : NOT_EQUAL; | 5511 Condition cond = IsDeoptIfNull() ? EQUAL : NOT_EQUAL; |
| 5749 __ j(cond, deopt); | 5512 __ j(cond, deopt); |
| 5750 } | 5513 } |
| 5751 | 5514 |
| 5752 | |
| 5753 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, | 5515 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, |
| 5754 intptr_t min, | 5516 intptr_t min, |
| 5755 intptr_t max, | 5517 intptr_t max, |
| 5756 intptr_t mask, | 5518 intptr_t mask, |
| 5757 Label* deopt) { | 5519 Label* deopt) { |
| 5758 Register biased_cid = locs()->temp(0).reg(); | 5520 Register biased_cid = locs()->temp(0).reg(); |
| 5759 __ subl(biased_cid, Immediate(min)); | 5521 __ subl(biased_cid, Immediate(min)); |
| 5760 __ cmpl(biased_cid, Immediate(max - min)); | 5522 __ cmpl(biased_cid, Immediate(max - min)); |
| 5761 __ j(ABOVE, deopt); | 5523 __ j(ABOVE, deopt); |
| 5762 | 5524 |
| 5763 Register mask_reg = locs()->temp(1).reg(); | 5525 Register mask_reg = locs()->temp(1).reg(); |
| 5764 __ movl(mask_reg, Immediate(mask)); | 5526 __ movl(mask_reg, Immediate(mask)); |
| 5765 __ bt(mask_reg, biased_cid); | 5527 __ bt(mask_reg, biased_cid); |
| 5766 __ j(NOT_CARRY, deopt); | 5528 __ j(NOT_CARRY, deopt); |
| 5767 } | 5529 } |
| 5768 | 5530 |
| 5769 | |
| 5770 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, | 5531 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, |
| 5771 int bias, | 5532 int bias, |
| 5772 intptr_t cid_start, | 5533 intptr_t cid_start, |
| 5773 intptr_t cid_end, | 5534 intptr_t cid_end, |
| 5774 bool is_last, | 5535 bool is_last, |
| 5775 Label* is_ok, | 5536 Label* is_ok, |
| 5776 Label* deopt, | 5537 Label* deopt, |
| 5777 bool use_near_jump) { | 5538 bool use_near_jump) { |
| 5778 Register biased_cid = locs()->temp(0).reg(); | 5539 Register biased_cid = locs()->temp(0).reg(); |
| 5779 Condition no_match, match; | 5540 Condition no_match, match; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5796 } else { | 5557 } else { |
| 5797 if (use_near_jump) { | 5558 if (use_near_jump) { |
| 5798 __ j(match, is_ok, Assembler::kNearJump); | 5559 __ j(match, is_ok, Assembler::kNearJump); |
| 5799 } else { | 5560 } else { |
| 5800 __ j(match, is_ok); | 5561 __ j(match, is_ok); |
| 5801 } | 5562 } |
| 5802 } | 5563 } |
| 5803 return bias; | 5564 return bias; |
| 5804 } | 5565 } |
| 5805 | 5566 |
| 5806 | |
| 5807 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5567 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
| 5808 bool opt) const { | 5568 bool opt) const { |
| 5809 const intptr_t kNumInputs = 1; | 5569 const intptr_t kNumInputs = 1; |
| 5810 const intptr_t kNumTemps = 0; | 5570 const intptr_t kNumTemps = 0; |
| 5811 LocationSummary* summary = new (zone) | 5571 LocationSummary* summary = new (zone) |
| 5812 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5572 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5813 summary->set_in(0, Location::RequiresRegister()); | 5573 summary->set_in(0, Location::RequiresRegister()); |
| 5814 return summary; | 5574 return summary; |
| 5815 } | 5575 } |
| 5816 | 5576 |
| 5817 | |
| 5818 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5577 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5819 Register value = locs()->in(0).reg(); | 5578 Register value = locs()->in(0).reg(); |
| 5820 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, | 5579 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
| 5821 licm_hoisted_ ? ICData::kHoisted : 0); | 5580 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5822 __ BranchIfNotSmi(value, deopt); | 5581 __ BranchIfNotSmi(value, deopt); |
| 5823 } | 5582 } |
| 5824 | 5583 |
| 5825 | |
| 5826 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5584 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
| 5827 bool opt) const { | 5585 bool opt) const { |
| 5828 const intptr_t kNumInputs = 1; | 5586 const intptr_t kNumInputs = 1; |
| 5829 const intptr_t kNumTemps = 0; | 5587 const intptr_t kNumTemps = 0; |
| 5830 LocationSummary* summary = new (zone) | 5588 LocationSummary* summary = new (zone) |
| 5831 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5589 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5832 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() | 5590 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() |
| 5833 : Location::WritableRegister()); | 5591 : Location::WritableRegister()); |
| 5834 return summary; | 5592 return summary; |
| 5835 } | 5593 } |
| 5836 | 5594 |
| 5837 | |
| 5838 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5595 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5839 Register value = locs()->in(0).reg(); | 5596 Register value = locs()->in(0).reg(); |
| 5840 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5597 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
| 5841 if (cids_.IsSingleCid()) { | 5598 if (cids_.IsSingleCid()) { |
| 5842 __ cmpl(value, Immediate(Smi::RawValue(cids_.cid_start))); | 5599 __ cmpl(value, Immediate(Smi::RawValue(cids_.cid_start))); |
| 5843 __ j(NOT_ZERO, deopt); | 5600 __ j(NOT_ZERO, deopt); |
| 5844 } else { | 5601 } else { |
| 5845 __ AddImmediate(value, Immediate(-Smi::RawValue(cids_.cid_start))); | 5602 __ AddImmediate(value, Immediate(-Smi::RawValue(cids_.cid_start))); |
| 5846 __ cmpl(value, Immediate(Smi::RawValue(cids_.Extent()))); | 5603 __ cmpl(value, Immediate(Smi::RawValue(cids_.Extent()))); |
| 5847 __ j(ABOVE, deopt); | 5604 __ j(ABOVE, deopt); |
| 5848 } | 5605 } |
| 5849 } | 5606 } |
| 5850 | 5607 |
| 5851 | |
| 5852 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5608 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
| 5853 bool opt) const { | 5609 bool opt) const { |
| 5854 // Only needed for AOT. | 5610 // Only needed for AOT. |
| 5855 UNIMPLEMENTED(); | 5611 UNIMPLEMENTED(); |
| 5856 return NULL; | 5612 return NULL; |
| 5857 } | 5613 } |
| 5858 | 5614 |
| 5859 | |
| 5860 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5615 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5861 // Only needed for AOT. | 5616 // Only needed for AOT. |
| 5862 UNIMPLEMENTED(); | 5617 UNIMPLEMENTED(); |
| 5863 } | 5618 } |
| 5864 | 5619 |
| 5865 | |
| 5866 // Length: register or constant. | 5620 // Length: register or constant. |
| 5867 // Index: register, constant or stack slot. | 5621 // Index: register, constant or stack slot. |
| 5868 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5622 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
| 5869 bool opt) const { | 5623 bool opt) const { |
| 5870 const intptr_t kNumInputs = 2; | 5624 const intptr_t kNumInputs = 2; |
| 5871 const intptr_t kNumTemps = 0; | 5625 const intptr_t kNumTemps = 0; |
| 5872 LocationSummary* locs = new (zone) | 5626 LocationSummary* locs = new (zone) |
| 5873 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5627 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5874 if (length()->definition()->IsConstant()) { | 5628 if (length()->definition()->IsConstant()) { |
| 5875 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5629 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
| 5876 } else { | 5630 } else { |
| 5877 locs->set_in(kLengthPos, Location::PrefersRegister()); | 5631 locs->set_in(kLengthPos, Location::PrefersRegister()); |
| 5878 } | 5632 } |
| 5879 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5633 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
| 5880 return locs; | 5634 return locs; |
| 5881 } | 5635 } |
| 5882 | 5636 |
| 5883 | |
| 5884 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5637 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5885 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5638 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
| 5886 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5639 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
| 5887 Label* deopt = | 5640 Label* deopt = |
| 5888 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); | 5641 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
| 5889 | 5642 |
| 5890 Location length_loc = locs()->in(kLengthPos); | 5643 Location length_loc = locs()->in(kLengthPos); |
| 5891 Location index_loc = locs()->in(kIndexPos); | 5644 Location index_loc = locs()->in(kIndexPos); |
| 5892 | 5645 |
| 5893 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5646 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5936 Register index = index_loc.reg(); | 5689 Register index = index_loc.reg(); |
| 5937 Register length = length_loc.reg(); | 5690 Register length = length_loc.reg(); |
| 5938 if (index_cid != kSmiCid) { | 5691 if (index_cid != kSmiCid) { |
| 5939 __ BranchIfNotSmi(index, deopt); | 5692 __ BranchIfNotSmi(index, deopt); |
| 5940 } | 5693 } |
| 5941 __ cmpl(length, index); | 5694 __ cmpl(length, index); |
| 5942 __ j(BELOW_EQUAL, deopt); | 5695 __ j(BELOW_EQUAL, deopt); |
| 5943 } | 5696 } |
| 5944 } | 5697 } |
| 5945 | 5698 |
| 5946 | |
| 5947 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5699 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 5948 bool opt) const { | 5700 bool opt) const { |
| 5949 const intptr_t kNumInputs = 2; | 5701 const intptr_t kNumInputs = 2; |
| 5950 switch (op_kind()) { | 5702 switch (op_kind()) { |
| 5951 case Token::kBIT_AND: | 5703 case Token::kBIT_AND: |
| 5952 case Token::kBIT_OR: | 5704 case Token::kBIT_OR: |
| 5953 case Token::kBIT_XOR: | 5705 case Token::kBIT_XOR: |
| 5954 case Token::kADD: | 5706 case Token::kADD: |
| 5955 case Token::kSUB: | 5707 case Token::kSUB: |
| 5956 case Token::kMUL: { | 5708 case Token::kMUL: { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5969 summary->set_temp(0, Location::RequiresRegister()); | 5721 summary->set_temp(0, Location::RequiresRegister()); |
| 5970 } | 5722 } |
| 5971 return summary; | 5723 return summary; |
| 5972 } | 5724 } |
| 5973 default: | 5725 default: |
| 5974 UNREACHABLE(); | 5726 UNREACHABLE(); |
| 5975 return NULL; | 5727 return NULL; |
| 5976 } | 5728 } |
| 5977 } | 5729 } |
| 5978 | 5730 |
| 5979 | |
| 5980 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5731 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5981 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 5732 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 5982 Register left_lo = left_pair->At(0).reg(); | 5733 Register left_lo = left_pair->At(0).reg(); |
| 5983 Register left_hi = left_pair->At(1).reg(); | 5734 Register left_hi = left_pair->At(1).reg(); |
| 5984 PairLocation* right_pair = locs()->in(1).AsPairLocation(); | 5735 PairLocation* right_pair = locs()->in(1).AsPairLocation(); |
| 5985 Register right_lo = right_pair->At(0).reg(); | 5736 Register right_lo = right_pair->At(0).reg(); |
| 5986 Register right_hi = right_pair->At(1).reg(); | 5737 Register right_hi = right_pair->At(1).reg(); |
| 5987 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 5738 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5988 Register out_lo = out_pair->At(0).reg(); | 5739 Register out_lo = out_pair->At(0).reg(); |
| 5989 Register out_hi = out_pair->At(1).reg(); | 5740 Register out_hi = out_pair->At(1).reg(); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6039 __ imull(right_lo); // Result in EDX:EAX. | 5790 __ imull(right_lo); // Result in EDX:EAX. |
| 6040 ASSERT(out_lo == EAX); | 5791 ASSERT(out_lo == EAX); |
| 6041 ASSERT(out_hi == EDX); | 5792 ASSERT(out_hi == EDX); |
| 6042 break; | 5793 break; |
| 6043 } | 5794 } |
| 6044 default: | 5795 default: |
| 6045 UNREACHABLE(); | 5796 UNREACHABLE(); |
| 6046 } | 5797 } |
| 6047 } | 5798 } |
| 6048 | 5799 |
| 6049 | |
| 6050 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 5800 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6051 bool opt) const { | 5801 bool opt) const { |
| 6052 const intptr_t kNumInputs = 2; | 5802 const intptr_t kNumInputs = 2; |
| 6053 const intptr_t kNumTemps = | 5803 const intptr_t kNumTemps = |
| 6054 (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0; | 5804 (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0; |
| 6055 LocationSummary* summary = new (zone) | 5805 LocationSummary* summary = new (zone) |
| 6056 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5806 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6057 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5807 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6058 Location::RequiresRegister())); | 5808 Location::RequiresRegister())); |
| 6059 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 5809 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 6060 if ((op_kind() == Token::kSHL) && CanDeoptimize()) { | 5810 if ((op_kind() == Token::kSHL) && CanDeoptimize()) { |
| 6061 summary->set_temp(0, Location::RequiresRegister()); | 5811 summary->set_temp(0, Location::RequiresRegister()); |
| 6062 summary->set_temp(1, Location::RequiresRegister()); | 5812 summary->set_temp(1, Location::RequiresRegister()); |
| 6063 } | 5813 } |
| 6064 summary->set_out(0, Location::SameAsFirstInput()); | 5814 summary->set_out(0, Location::SameAsFirstInput()); |
| 6065 return summary; | 5815 return summary; |
| 6066 } | 5816 } |
| 6067 | 5817 |
| 6068 | |
| 6069 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5818 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6070 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 5819 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 6071 Register left_lo = left_pair->At(0).reg(); | 5820 Register left_lo = left_pair->At(0).reg(); |
| 6072 Register left_hi = left_pair->At(1).reg(); | 5821 Register left_hi = left_pair->At(1).reg(); |
| 6073 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 5822 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 6074 Register out_lo = out_pair->At(0).reg(); | 5823 Register out_lo = out_pair->At(0).reg(); |
| 6075 Register out_hi = out_pair->At(1).reg(); | 5824 Register out_hi = out_pair->At(1).reg(); |
| 6076 ASSERT(out_lo == left_lo); | 5825 ASSERT(out_lo == left_lo); |
| 6077 ASSERT(out_hi == left_hi); | 5826 ASSERT(out_hi == left_hi); |
| 6078 | 5827 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6231 } | 5980 } |
| 6232 break; | 5981 break; |
| 6233 } | 5982 } |
| 6234 default: | 5983 default: |
| 6235 UNREACHABLE(); | 5984 UNREACHABLE(); |
| 6236 } | 5985 } |
| 6237 __ Bind(&done); | 5986 __ Bind(&done); |
| 6238 } | 5987 } |
| 6239 } | 5988 } |
| 6240 | 5989 |
| 6241 | |
| 6242 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5990 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6243 bool opt) const { | 5991 bool opt) const { |
| 6244 const intptr_t kNumInputs = 1; | 5992 const intptr_t kNumInputs = 1; |
| 6245 const intptr_t kNumTemps = 0; | 5993 const intptr_t kNumTemps = 0; |
| 6246 LocationSummary* summary = new (zone) | 5994 LocationSummary* summary = new (zone) |
| 6247 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5995 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6248 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5996 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6249 Location::RequiresRegister())); | 5997 Location::RequiresRegister())); |
| 6250 summary->set_out(0, Location::SameAsFirstInput()); | 5998 summary->set_out(0, Location::SameAsFirstInput()); |
| 6251 return summary; | 5999 return summary; |
| 6252 } | 6000 } |
| 6253 | 6001 |
| 6254 | |
| 6255 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6002 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6256 ASSERT(op_kind() == Token::kBIT_NOT); | 6003 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6257 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6004 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 6258 Register left_lo = left_pair->At(0).reg(); | 6005 Register left_lo = left_pair->At(0).reg(); |
| 6259 Register left_hi = left_pair->At(1).reg(); | 6006 Register left_hi = left_pair->At(1).reg(); |
| 6260 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6007 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 6261 Register out_lo = out_pair->At(0).reg(); | 6008 Register out_lo = out_pair->At(0).reg(); |
| 6262 Register out_hi = out_pair->At(1).reg(); | 6009 Register out_hi = out_pair->At(1).reg(); |
| 6263 ASSERT(out_lo == left_lo); | 6010 ASSERT(out_lo == left_lo); |
| 6264 ASSERT(out_hi == left_hi); | 6011 ASSERT(out_hi == left_hi); |
| 6265 __ notl(left_lo); | 6012 __ notl(left_lo); |
| 6266 __ notl(left_hi); | 6013 __ notl(left_hi); |
| 6267 } | 6014 } |
| 6268 | 6015 |
| 6269 | |
| 6270 CompileType BinaryUint32OpInstr::ComputeType() const { | 6016 CompileType BinaryUint32OpInstr::ComputeType() const { |
| 6271 return CompileType::Int(); | 6017 return CompileType::Int(); |
| 6272 } | 6018 } |
| 6273 | 6019 |
| 6274 | |
| 6275 CompileType ShiftUint32OpInstr::ComputeType() const { | 6020 CompileType ShiftUint32OpInstr::ComputeType() const { |
| 6276 return CompileType::Int(); | 6021 return CompileType::Int(); |
| 6277 } | 6022 } |
| 6278 | 6023 |
| 6279 | |
| 6280 CompileType UnaryUint32OpInstr::ComputeType() const { | 6024 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 6281 return CompileType::Int(); | 6025 return CompileType::Int(); |
| 6282 } | 6026 } |
| 6283 | 6027 |
| 6284 | |
| 6285 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 6028 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6286 bool opt) const { | 6029 bool opt) const { |
| 6287 const intptr_t kNumInputs = 2; | 6030 const intptr_t kNumInputs = 2; |
| 6288 const intptr_t kNumTemps = 0; | 6031 const intptr_t kNumTemps = 0; |
| 6289 LocationSummary* summary = new (zone) | 6032 LocationSummary* summary = new (zone) |
| 6290 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6033 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6291 summary->set_in(0, Location::RequiresRegister()); | 6034 summary->set_in(0, Location::RequiresRegister()); |
| 6292 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 6035 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 6293 summary->set_out(0, Location::SameAsFirstInput()); | 6036 summary->set_out(0, Location::SameAsFirstInput()); |
| 6294 return summary; | 6037 return summary; |
| 6295 } | 6038 } |
| 6296 | 6039 |
| 6297 | |
| 6298 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6040 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6299 const intptr_t kShifterLimit = 31; | 6041 const intptr_t kShifterLimit = 31; |
| 6300 | 6042 |
| 6301 Register left = locs()->in(0).reg(); | 6043 Register left = locs()->in(0).reg(); |
| 6302 Register out = locs()->out(0).reg(); | 6044 Register out = locs()->out(0).reg(); |
| 6303 ASSERT(left == out); | 6045 ASSERT(left == out); |
| 6304 | 6046 |
| 6305 | |
| 6306 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6047 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 6307 | 6048 |
| 6308 if (locs()->in(1).IsConstant()) { | 6049 if (locs()->in(1).IsConstant()) { |
| 6309 // Shifter is constant. | 6050 // Shifter is constant. |
| 6310 | 6051 |
| 6311 const Object& constant = locs()->in(1).constant(); | 6052 const Object& constant = locs()->in(1).constant(); |
| 6312 ASSERT(constant.IsSmi()); | 6053 ASSERT(constant.IsSmi()); |
| 6313 const intptr_t shift_value = Smi::Cast(constant).Value(); | 6054 const intptr_t shift_value = Smi::Cast(constant).Value(); |
| 6314 | 6055 |
| 6315 | |
| 6316 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | 6056 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
| 6317 switch (op_kind()) { | 6057 switch (op_kind()) { |
| 6318 case Token::kSHR: | 6058 case Token::kSHR: |
| 6319 __ shrl(left, Immediate(shift_value)); | 6059 __ shrl(left, Immediate(shift_value)); |
| 6320 break; | 6060 break; |
| 6321 case Token::kSHL: | 6061 case Token::kSHL: |
| 6322 __ shll(left, Immediate(shift_value)); | 6062 __ shll(left, Immediate(shift_value)); |
| 6323 break; | 6063 break; |
| 6324 default: | 6064 default: |
| 6325 UNREACHABLE(); | 6065 UNREACHABLE(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6359 } | 6099 } |
| 6360 | 6100 |
| 6361 __ Bind(&zero); | 6101 __ Bind(&zero); |
| 6362 // Shift was greater than 31 bits, just return zero. | 6102 // Shift was greater than 31 bits, just return zero. |
| 6363 __ xorl(left, left); | 6103 __ xorl(left, left); |
| 6364 | 6104 |
| 6365 // Exit path. | 6105 // Exit path. |
| 6366 __ Bind(&done); | 6106 __ Bind(&done); |
| 6367 } | 6107 } |
| 6368 | 6108 |
| 6369 | |
| 6370 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6109 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6371 bool opt) const { | 6110 bool opt) const { |
| 6372 const intptr_t kNumInputs = 1; | 6111 const intptr_t kNumInputs = 1; |
| 6373 const intptr_t kNumTemps = 0; | 6112 const intptr_t kNumTemps = 0; |
| 6374 LocationSummary* summary = new (zone) | 6113 LocationSummary* summary = new (zone) |
| 6375 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6114 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6376 summary->set_in(0, Location::RequiresRegister()); | 6115 summary->set_in(0, Location::RequiresRegister()); |
| 6377 summary->set_out(0, Location::SameAsFirstInput()); | 6116 summary->set_out(0, Location::SameAsFirstInput()); |
| 6378 return summary; | 6117 return summary; |
| 6379 } | 6118 } |
| 6380 | 6119 |
| 6381 | |
| 6382 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6120 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6383 Register out = locs()->out(0).reg(); | 6121 Register out = locs()->out(0).reg(); |
| 6384 ASSERT(locs()->in(0).reg() == out); | 6122 ASSERT(locs()->in(0).reg() == out); |
| 6385 | 6123 |
| 6386 ASSERT(op_kind() == Token::kBIT_NOT); | 6124 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6387 | 6125 |
| 6388 __ notl(out); | 6126 __ notl(out); |
| 6389 } | 6127 } |
| 6390 | 6128 |
| 6391 | |
| 6392 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 6129 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
| 6393 bool opt) const { | 6130 bool opt) const { |
| 6394 const intptr_t kNumInputs = 1; | 6131 const intptr_t kNumInputs = 1; |
| 6395 const intptr_t kNumTemps = 0; | 6132 const intptr_t kNumTemps = 0; |
| 6396 LocationSummary* summary = new (zone) | 6133 LocationSummary* summary = new (zone) |
| 6397 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6134 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6398 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) && | 6135 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) && |
| 6399 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) { | 6136 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) { |
| 6400 summary->set_in(0, Location::RequiresRegister()); | 6137 summary->set_in(0, Location::RequiresRegister()); |
| 6401 summary->set_out(0, Location::SameAsFirstInput()); | 6138 summary->set_out(0, Location::SameAsFirstInput()); |
| 6402 } else if (from() == kUnboxedMint) { | 6139 } else if (from() == kUnboxedMint) { |
| 6403 summary->set_in( | 6140 summary->set_in( |
| 6404 0, Location::Pair(CanDeoptimize() ? Location::WritableRegister() | 6141 0, Location::Pair(CanDeoptimize() ? Location::WritableRegister() |
| 6405 : Location::RequiresRegister(), | 6142 : Location::RequiresRegister(), |
| 6406 Location::RequiresRegister())); | 6143 Location::RequiresRegister())); |
| 6407 summary->set_out(0, Location::RequiresRegister()); | 6144 summary->set_out(0, Location::RequiresRegister()); |
| 6408 } else if (from() == kUnboxedUint32) { | 6145 } else if (from() == kUnboxedUint32) { |
| 6409 summary->set_in(0, Location::RequiresRegister()); | 6146 summary->set_in(0, Location::RequiresRegister()); |
| 6410 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6147 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 6411 Location::RequiresRegister())); | 6148 Location::RequiresRegister())); |
| 6412 } else if (from() == kUnboxedInt32) { | 6149 } else if (from() == kUnboxedInt32) { |
| 6413 summary->set_in(0, Location::RegisterLocation(EAX)); | 6150 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 6414 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 6151 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
| 6415 Location::RegisterLocation(EDX))); | 6152 Location::RegisterLocation(EDX))); |
| 6416 } | 6153 } |
| 6417 return summary; | 6154 return summary; |
| 6418 } | 6155 } |
| 6419 | 6156 |
| 6420 | |
| 6421 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6157 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6422 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { | 6158 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
| 6423 // Representations are bitwise equivalent. | 6159 // Representations are bitwise equivalent. |
| 6424 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); | 6160 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); |
| 6425 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { | 6161 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { |
| 6426 // Representations are bitwise equivalent. | 6162 // Representations are bitwise equivalent. |
| 6427 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); | 6163 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); |
| 6428 if (CanDeoptimize()) { | 6164 if (CanDeoptimize()) { |
| 6429 Label* deopt = | 6165 Label* deopt = |
| 6430 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | 6166 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6466 Register out_lo = out_pair->At(0).reg(); | 6202 Register out_lo = out_pair->At(0).reg(); |
| 6467 Register out_hi = out_pair->At(1).reg(); | 6203 Register out_hi = out_pair->At(1).reg(); |
| 6468 ASSERT(locs()->in(0).reg() == EAX); | 6204 ASSERT(locs()->in(0).reg() == EAX); |
| 6469 ASSERT(out_lo == EAX && out_hi == EDX); | 6205 ASSERT(out_lo == EAX && out_hi == EDX); |
| 6470 __ cdq(); | 6206 __ cdq(); |
| 6471 } else { | 6207 } else { |
| 6472 UNREACHABLE(); | 6208 UNREACHABLE(); |
| 6473 } | 6209 } |
| 6474 } | 6210 } |
| 6475 | 6211 |
| 6476 | |
| 6477 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6212 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6478 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 6213 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 6479 } | 6214 } |
| 6480 | 6215 |
| 6481 | |
| 6482 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6216 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6483 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, | 6217 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
| 6484 locs()); | 6218 locs()); |
| 6485 __ int3(); | 6219 __ int3(); |
| 6486 } | 6220 } |
| 6487 | 6221 |
| 6488 | |
| 6489 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6222 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6490 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 6223 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 6491 } | 6224 } |
| 6492 | 6225 |
| 6493 | |
| 6494 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6226 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6495 compiler->SetNeedsStackTrace(catch_try_index()); | 6227 compiler->SetNeedsStackTrace(catch_try_index()); |
| 6496 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, | 6228 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
| 6497 2, locs()); | 6229 2, locs()); |
| 6498 __ int3(); | 6230 __ int3(); |
| 6499 } | 6231 } |
| 6500 | 6232 |
| 6501 | |
| 6502 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6233 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6503 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 6234 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 6504 } | 6235 } |
| 6505 | 6236 |
| 6506 | |
| 6507 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6237 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6508 __ Stop(message()); | 6238 __ Stop(message()); |
| 6509 } | 6239 } |
| 6510 | 6240 |
| 6511 | |
| 6512 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6241 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6513 if (!compiler->CanFallThroughTo(normal_entry())) { | 6242 if (!compiler->CanFallThroughTo(normal_entry())) { |
| 6514 __ jmp(compiler->GetJumpLabel(normal_entry())); | 6243 __ jmp(compiler->GetJumpLabel(normal_entry())); |
| 6515 } | 6244 } |
| 6516 } | 6245 } |
| 6517 | 6246 |
| 6518 | |
| 6519 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6247 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6520 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 6248 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 6521 } | 6249 } |
| 6522 | 6250 |
| 6523 | |
| 6524 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6251 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6525 if (!compiler->is_optimizing()) { | 6252 if (!compiler->is_optimizing()) { |
| 6526 if (FLAG_reorder_basic_blocks) { | 6253 if (FLAG_reorder_basic_blocks) { |
| 6527 compiler->EmitEdgeCounter(block()->preorder_number()); | 6254 compiler->EmitEdgeCounter(block()->preorder_number()); |
| 6528 } | 6255 } |
| 6529 // Add a deoptimization descriptor for deoptimizing instructions that | 6256 // Add a deoptimization descriptor for deoptimizing instructions that |
| 6530 // may be inserted before this instruction. | 6257 // may be inserted before this instruction. |
| 6531 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), | 6258 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
| 6532 TokenPosition::kNoSource); | 6259 TokenPosition::kNoSource); |
| 6533 } | 6260 } |
| 6534 if (HasParallelMove()) { | 6261 if (HasParallelMove()) { |
| 6535 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 6262 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 6536 } | 6263 } |
| 6537 | 6264 |
| 6538 // We can fall through if the successor is the next block in the list. | 6265 // We can fall through if the successor is the next block in the list. |
| 6539 // Otherwise, we need a jump. | 6266 // Otherwise, we need a jump. |
| 6540 if (!compiler->CanFallThroughTo(successor())) { | 6267 if (!compiler->CanFallThroughTo(successor())) { |
| 6541 __ jmp(compiler->GetJumpLabel(successor())); | 6268 __ jmp(compiler->GetJumpLabel(successor())); |
| 6542 } | 6269 } |
| 6543 } | 6270 } |
| 6544 | 6271 |
| 6545 | |
| 6546 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 6272 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
| 6547 bool opt) const { | 6273 bool opt) const { |
| 6548 const intptr_t kNumInputs = 1; | 6274 const intptr_t kNumInputs = 1; |
| 6549 const intptr_t kNumTemps = 1; | 6275 const intptr_t kNumTemps = 1; |
| 6550 | 6276 |
| 6551 LocationSummary* summary = new (zone) | 6277 LocationSummary* summary = new (zone) |
| 6552 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6278 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6553 | 6279 |
| 6554 summary->set_in(0, Location::RequiresRegister()); | 6280 summary->set_in(0, Location::RequiresRegister()); |
| 6555 summary->set_temp(0, Location::RequiresRegister()); | 6281 summary->set_temp(0, Location::RequiresRegister()); |
| 6556 | 6282 |
| 6557 return summary; | 6283 return summary; |
| 6558 } | 6284 } |
| 6559 | 6285 |
| 6560 | |
| 6561 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6286 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6562 Register target_reg = locs()->temp_slot(0)->reg(); | 6287 Register target_reg = locs()->temp_slot(0)->reg(); |
| 6563 | 6288 |
| 6564 // Load code object from frame. | 6289 // Load code object from frame. |
| 6565 __ movl(target_reg, Address(EBP, kPcMarkerSlotFromFp * kWordSize)); | 6290 __ movl(target_reg, Address(EBP, kPcMarkerSlotFromFp * kWordSize)); |
| 6566 // Load instructions object (active_instructions and Code::entry_point() may | 6291 // Load instructions object (active_instructions and Code::entry_point() may |
| 6567 // not point to this instruction object any more; see Code::DisableDartCode). | 6292 // not point to this instruction object any more; see Code::DisableDartCode). |
| 6568 __ movl(target_reg, | 6293 __ movl(target_reg, |
| 6569 FieldAddress(target_reg, Code::saved_instructions_offset())); | 6294 FieldAddress(target_reg, Code::saved_instructions_offset())); |
| 6570 __ addl(target_reg, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 6295 __ addl(target_reg, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 6571 | 6296 |
| 6572 // Add the offset. | 6297 // Add the offset. |
| 6573 Register offset_reg = locs()->in(0).reg(); | 6298 Register offset_reg = locs()->in(0).reg(); |
| 6574 if (offset()->definition()->representation() == kTagged) { | 6299 if (offset()->definition()->representation() == kTagged) { |
| 6575 __ SmiUntag(offset_reg); | 6300 __ SmiUntag(offset_reg); |
| 6576 } | 6301 } |
| 6577 __ addl(target_reg, offset_reg); | 6302 __ addl(target_reg, offset_reg); |
| 6578 | 6303 |
| 6579 // Jump to the absolute address. | 6304 // Jump to the absolute address. |
| 6580 __ jmp(target_reg); | 6305 __ jmp(target_reg); |
| 6581 } | 6306 } |
| 6582 | 6307 |
| 6583 | |
| 6584 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 6308 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
| 6585 bool opt) const { | 6309 bool opt) const { |
| 6586 const intptr_t kNumInputs = 2; | 6310 const intptr_t kNumInputs = 2; |
| 6587 const intptr_t kNumTemps = 0; | 6311 const intptr_t kNumTemps = 0; |
| 6588 if (needs_number_check()) { | 6312 if (needs_number_check()) { |
| 6589 LocationSummary* locs = new (zone) | 6313 LocationSummary* locs = new (zone) |
| 6590 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6314 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6591 locs->set_in(0, Location::RegisterLocation(EAX)); | 6315 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 6592 locs->set_in(1, Location::RegisterLocation(ECX)); | 6316 locs->set_in(1, Location::RegisterLocation(ECX)); |
| 6593 locs->set_out(0, Location::RegisterLocation(EAX)); | 6317 locs->set_out(0, Location::RegisterLocation(EAX)); |
| 6594 return locs; | 6318 return locs; |
| 6595 } | 6319 } |
| 6596 LocationSummary* locs = new (zone) | 6320 LocationSummary* locs = new (zone) |
| 6597 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6321 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6598 locs->set_in(0, Location::RegisterOrConstant(left())); | 6322 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 6599 // Only one of the inputs can be a constant. Choose register if the first one | 6323 // Only one of the inputs can be a constant. Choose register if the first one |
| 6600 // is a constant. | 6324 // is a constant. |
| 6601 locs->set_in(1, locs->in(0).IsConstant() | 6325 locs->set_in(1, locs->in(0).IsConstant() |
| 6602 ? Location::RequiresRegister() | 6326 ? Location::RequiresRegister() |
| 6603 : Location::RegisterOrConstant(right())); | 6327 : Location::RegisterOrConstant(right())); |
| 6604 locs->set_out(0, Location::RequiresRegister()); | 6328 locs->set_out(0, Location::RequiresRegister()); |
| 6605 return locs; | 6329 return locs; |
| 6606 } | 6330 } |
| 6607 | 6331 |
| 6608 | |
| 6609 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 6332 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 6610 BranchLabels labels) { | 6333 BranchLabels labels) { |
| 6611 Location left = locs()->in(0); | 6334 Location left = locs()->in(0); |
| 6612 Location right = locs()->in(1); | 6335 Location right = locs()->in(1); |
| 6613 ASSERT(!left.IsConstant() || !right.IsConstant()); | 6336 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 6614 Condition true_condition; | 6337 Condition true_condition; |
| 6615 if (left.IsConstant()) { | 6338 if (left.IsConstant()) { |
| 6616 true_condition = compiler->EmitEqualityRegConstCompare( | 6339 true_condition = compiler->EmitEqualityRegConstCompare( |
| 6617 right.reg(), left.constant(), needs_number_check(), token_pos(), | 6340 right.reg(), left.constant(), needs_number_check(), token_pos(), |
| 6618 deopt_id_); | 6341 deopt_id_); |
| 6619 } else if (right.IsConstant()) { | 6342 } else if (right.IsConstant()) { |
| 6620 true_condition = compiler->EmitEqualityRegConstCompare( | 6343 true_condition = compiler->EmitEqualityRegConstCompare( |
| 6621 left.reg(), right.constant(), needs_number_check(), token_pos(), | 6344 left.reg(), right.constant(), needs_number_check(), token_pos(), |
| 6622 deopt_id_); | 6345 deopt_id_); |
| 6623 } else { | 6346 } else { |
| 6624 true_condition = compiler->EmitEqualityRegRegCompare( | 6347 true_condition = compiler->EmitEqualityRegRegCompare( |
| 6625 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 6348 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
| 6626 } | 6349 } |
| 6627 if (kind() != Token::kEQ_STRICT) { | 6350 if (kind() != Token::kEQ_STRICT) { |
| 6628 ASSERT(kind() == Token::kNE_STRICT); | 6351 ASSERT(kind() == Token::kNE_STRICT); |
| 6629 true_condition = NegateCondition(true_condition); | 6352 true_condition = NegateCondition(true_condition); |
| 6630 } | 6353 } |
| 6631 return true_condition; | 6354 return true_condition; |
| 6632 } | 6355 } |
| 6633 | 6356 |
| 6634 | |
| 6635 // Detect pattern when one value is zero and another is a power of 2. | 6357 // Detect pattern when one value is zero and another is a power of 2. |
| 6636 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 6358 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 6637 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 6359 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 6638 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 6360 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 6639 } | 6361 } |
| 6640 | 6362 |
| 6641 | |
| 6642 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 6363 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
| 6643 bool opt) const { | 6364 bool opt) const { |
| 6644 comparison()->InitializeLocationSummary(zone, opt); | 6365 comparison()->InitializeLocationSummary(zone, opt); |
| 6645 // TODO(vegorov): support byte register constraints in the register allocator. | 6366 // TODO(vegorov): support byte register constraints in the register allocator. |
| 6646 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX)); | 6367 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX)); |
| 6647 return comparison()->locs(); | 6368 return comparison()->locs(); |
| 6648 } | 6369 } |
| 6649 | 6370 |
| 6650 | |
| 6651 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6371 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6652 ASSERT(locs()->out(0).reg() == EDX); | 6372 ASSERT(locs()->out(0).reg() == EDX); |
| 6653 | 6373 |
| 6654 // Clear upper part of the out register. We are going to use setcc on it | 6374 // Clear upper part of the out register. We are going to use setcc on it |
| 6655 // which is a byte move. | 6375 // which is a byte move. |
| 6656 __ xorl(EDX, EDX); | 6376 __ xorl(EDX, EDX); |
| 6657 | 6377 |
| 6658 // Emit comparison code. This must not overwrite the result register. | 6378 // Emit comparison code. This must not overwrite the result register. |
| 6659 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using | 6379 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using |
| 6660 // the labels or returning an invalid condition. | 6380 // the labels or returning an invalid condition. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6692 } else { | 6412 } else { |
| 6693 __ decl(EDX); | 6413 __ decl(EDX); |
| 6694 __ andl(EDX, | 6414 __ andl(EDX, |
| 6695 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); | 6415 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); |
| 6696 if (false_value != 0) { | 6416 if (false_value != 0) { |
| 6697 __ addl(EDX, Immediate(Smi::RawValue(false_value))); | 6417 __ addl(EDX, Immediate(Smi::RawValue(false_value))); |
| 6698 } | 6418 } |
| 6699 } | 6419 } |
| 6700 } | 6420 } |
| 6701 | 6421 |
| 6702 | |
| 6703 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 6422 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
| 6704 bool opt) const { | 6423 bool opt) const { |
| 6705 const intptr_t kNumInputs = 1; | 6424 const intptr_t kNumInputs = 1; |
| 6706 const intptr_t kNumTemps = 0; | 6425 const intptr_t kNumTemps = 0; |
| 6707 LocationSummary* summary = new (zone) | 6426 LocationSummary* summary = new (zone) |
| 6708 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6427 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6709 summary->set_in(0, Location::RegisterLocation(EAX)); // Function. | 6428 summary->set_in(0, Location::RegisterLocation(EAX)); // Function. |
| 6710 summary->set_out(0, Location::RegisterLocation(EAX)); | 6429 summary->set_out(0, Location::RegisterLocation(EAX)); |
| 6711 return summary; | 6430 return summary; |
| 6712 } | 6431 } |
| 6713 | 6432 |
| 6714 | |
| 6715 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6433 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6716 // Load arguments descriptor. | 6434 // Load arguments descriptor. |
| 6717 const intptr_t argument_count = ArgumentCount(); // Includes type args. | 6435 const intptr_t argument_count = ArgumentCount(); // Includes type args. |
| 6718 const Array& arguments_descriptor = | 6436 const Array& arguments_descriptor = |
| 6719 Array::ZoneHandle(Z, GetArgumentsDescriptor()); | 6437 Array::ZoneHandle(Z, GetArgumentsDescriptor()); |
| 6720 __ LoadObject(EDX, arguments_descriptor); | 6438 __ LoadObject(EDX, arguments_descriptor); |
| 6721 | 6439 |
| 6722 // EBX: Code (compiled code or lazy compile stub). | 6440 // EBX: Code (compiled code or lazy compile stub). |
| 6723 ASSERT(locs()->in(0).reg() == EAX); | 6441 ASSERT(locs()->in(0).reg() == EAX); |
| 6724 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); | 6442 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 6736 compiler->AddDeoptIndexAtCall(deopt_id_after); | 6454 compiler->AddDeoptIndexAtCall(deopt_id_after); |
| 6737 } | 6455 } |
| 6738 // Add deoptimization continuation point after the call and before the | 6456 // Add deoptimization continuation point after the call and before the |
| 6739 // arguments are removed. | 6457 // arguments are removed. |
| 6740 // In optimized code this descriptor is needed for exception handling. | 6458 // In optimized code this descriptor is needed for exception handling. |
| 6741 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, | 6459 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
| 6742 token_pos()); | 6460 token_pos()); |
| 6743 __ Drop(argument_count); | 6461 __ Drop(argument_count); |
| 6744 } | 6462 } |
| 6745 | 6463 |
| 6746 | |
| 6747 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 6464 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
| 6748 bool opt) const { | 6465 bool opt) const { |
| 6749 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), | 6466 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
| 6750 LocationSummary::kNoCall); | 6467 LocationSummary::kNoCall); |
| 6751 } | 6468 } |
| 6752 | 6469 |
| 6753 | |
| 6754 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6470 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6755 Register value = locs()->in(0).reg(); | 6471 Register value = locs()->in(0).reg(); |
| 6756 Register result = locs()->out(0).reg(); | 6472 Register result = locs()->out(0).reg(); |
| 6757 | 6473 |
| 6758 Label done; | 6474 Label done; |
| 6759 __ LoadObject(result, Bool::True()); | 6475 __ LoadObject(result, Bool::True()); |
| 6760 __ CompareRegisters(result, value); | 6476 __ CompareRegisters(result, value); |
| 6761 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 6477 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 6762 __ LoadObject(result, Bool::False()); | 6478 __ LoadObject(result, Bool::False()); |
| 6763 __ Bind(&done); | 6479 __ Bind(&done); |
| 6764 } | 6480 } |
| 6765 | 6481 |
| 6766 | |
| 6767 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 6482 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
| 6768 bool opt) const { | 6483 bool opt) const { |
| 6769 return MakeCallSummary(zone); | 6484 return MakeCallSummary(zone); |
| 6770 } | 6485 } |
| 6771 | 6486 |
| 6772 | |
| 6773 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6487 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6774 const Code& stub = Code::ZoneHandle( | 6488 const Code& stub = Code::ZoneHandle( |
| 6775 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 6489 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
| 6776 const StubEntry stub_entry(stub); | 6490 const StubEntry stub_entry(stub); |
| 6777 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, | 6491 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
| 6778 locs()); | 6492 locs()); |
| 6779 compiler->AddStubCallTarget(stub); | 6493 compiler->AddStubCallTarget(stub); |
| 6780 __ Drop(ArgumentCount()); // Discard arguments. | 6494 __ Drop(ArgumentCount()); // Discard arguments. |
| 6781 } | 6495 } |
| 6782 | 6496 |
| 6783 | |
| 6784 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6497 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6785 ASSERT(!compiler->is_optimizing()); | 6498 ASSERT(!compiler->is_optimizing()); |
| 6786 __ Call(*StubCode::DebugStepCheck_entry()); | 6499 __ Call(*StubCode::DebugStepCheck_entry()); |
| 6787 compiler->EmitCallsiteMetaData(token_pos(), deopt_id_, stub_kind_, locs()); | 6500 compiler->EmitCallsiteMetaData(token_pos(), deopt_id_, stub_kind_, locs()); |
| 6788 } | 6501 } |
| 6789 | 6502 |
| 6790 | |
| 6791 } // namespace dart | 6503 } // namespace dart |
| 6792 | 6504 |
| 6793 #undef __ | 6505 #undef __ |
| 6794 | 6506 |
| 6795 #endif // defined TARGET_ARCH_IA32 | 6507 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |