| 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/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 if (!locs()->out(0).IsInvalid()) { | 154 if (!locs()->out(0).IsInvalid()) { |
| 155 Register result = locs()->out(0).reg(); | 155 Register result = locs()->out(0).reg(); |
| 156 __ LoadObjectSafely(result, value()); | 156 __ LoadObjectSafely(result, value()); |
| 157 } | 157 } |
| 158 } | 158 } |
| 159 | 159 |
| 160 | 160 |
| 161 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Isolate* isolate, | 161 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Isolate* isolate, |
| 162 bool opt) const { | 162 bool opt) const { |
| 163 const intptr_t kNumInputs = 0; | 163 const intptr_t kNumInputs = 0; |
| 164 const intptr_t kNumTemps = (constant_address() == 0) ? 1 : 0; | 164 const intptr_t kNumTemps = |
| 165 (constant_address() == 0) && (representation() != kUnboxedInt32) ? 1 : 0; |
| 165 LocationSummary* locs = new(isolate) LocationSummary( | 166 LocationSummary* locs = new(isolate) LocationSummary( |
| 166 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 167 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 167 locs->set_out(0, Location::RequiresFpuRegister()); | 168 if (representation() == kUnboxedDouble) { |
| 169 locs->set_out(0, Location::RequiresFpuRegister()); |
| 170 } else { |
| 171 ASSERT(representation() == kUnboxedInt32); |
| 172 locs->set_out(0, Location::RequiresRegister()); |
| 173 } |
| 168 if (kNumTemps == 1) { | 174 if (kNumTemps == 1) { |
| 169 locs->set_temp(0, Location::RequiresRegister()); | 175 locs->set_temp(0, Location::RequiresRegister()); |
| 170 } | 176 } |
| 171 return locs; | 177 return locs; |
| 172 } | 178 } |
| 173 | 179 |
| 174 | 180 |
| 175 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 181 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 176 // The register allocator drops constant definitions that have no uses. | 182 // The register allocator drops constant definitions that have no uses. |
| 177 if (!locs()->out(0).IsInvalid()) { | 183 if (!locs()->out(0).IsInvalid()) { |
| (...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1214 case kOneByteStringCid: | 1220 case kOneByteStringCid: |
| 1215 case kTypedDataInt8ArrayCid: | 1221 case kTypedDataInt8ArrayCid: |
| 1216 case kTypedDataUint8ArrayCid: | 1222 case kTypedDataUint8ArrayCid: |
| 1217 case kExternalTypedDataUint8ArrayCid: | 1223 case kExternalTypedDataUint8ArrayCid: |
| 1218 case kTypedDataUint8ClampedArrayCid: | 1224 case kTypedDataUint8ClampedArrayCid: |
| 1219 case kExternalTypedDataUint8ClampedArrayCid: | 1225 case kExternalTypedDataUint8ClampedArrayCid: |
| 1220 case kTypedDataInt16ArrayCid: | 1226 case kTypedDataInt16ArrayCid: |
| 1221 case kTypedDataUint16ArrayCid: | 1227 case kTypedDataUint16ArrayCid: |
| 1222 return kTagged; | 1228 return kTagged; |
| 1223 case kTypedDataInt32ArrayCid: | 1229 case kTypedDataInt32ArrayCid: |
| 1230 return kUnboxedInt32; |
| 1224 case kTypedDataUint32ArrayCid: | 1231 case kTypedDataUint32ArrayCid: |
| 1225 return value()->IsSmiValue() ? kTagged : kUnboxedMint; | 1232 return kUnboxedUint32; |
| 1226 case kTypedDataFloat32ArrayCid: | 1233 case kTypedDataFloat32ArrayCid: |
| 1227 case kTypedDataFloat64ArrayCid: | 1234 case kTypedDataFloat64ArrayCid: |
| 1228 return kUnboxedDouble; | 1235 return kUnboxedDouble; |
| 1229 case kTypedDataFloat32x4ArrayCid: | 1236 case kTypedDataFloat32x4ArrayCid: |
| 1230 return kUnboxedFloat32x4; | 1237 return kUnboxedFloat32x4; |
| 1231 case kTypedDataInt32x4ArrayCid: | 1238 case kTypedDataInt32x4ArrayCid: |
| 1232 return kUnboxedInt32x4; | 1239 return kUnboxedInt32x4; |
| 1233 case kTypedDataFloat64x2ArrayCid: | 1240 case kTypedDataFloat64x2ArrayCid: |
| 1234 return kUnboxedFloat64x2; | 1241 return kUnboxedFloat64x2; |
| 1235 default: | 1242 default: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 // EBX, ECX, EDX) instead of using a fixed register. | 1279 // EBX, ECX, EDX) instead of using a fixed register. |
| 1273 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); | 1280 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); |
| 1274 break; | 1281 break; |
| 1275 case kTypedDataInt16ArrayCid: | 1282 case kTypedDataInt16ArrayCid: |
| 1276 case kTypedDataUint16ArrayCid: | 1283 case kTypedDataUint16ArrayCid: |
| 1277 // Writable register because the value must be untagged before storing. | 1284 // Writable register because the value must be untagged before storing. |
| 1278 locs->set_in(2, Location::WritableRegister()); | 1285 locs->set_in(2, Location::WritableRegister()); |
| 1279 break; | 1286 break; |
| 1280 case kTypedDataInt32ArrayCid: | 1287 case kTypedDataInt32ArrayCid: |
| 1281 case kTypedDataUint32ArrayCid: | 1288 case kTypedDataUint32ArrayCid: |
| 1282 // For smis, use a writable register because the value must be untagged | 1289 locs->set_in(2, Location::RequiresRegister()); |
| 1283 // before storing. Mints are stored in registers pairs. | |
| 1284 if (value()->IsSmiValue()) { | |
| 1285 locs->set_in(2, Location::WritableRegister()); | |
| 1286 } else { | |
| 1287 // We only move the lower 32-bits so we don't care where the high bits | |
| 1288 // are located. | |
| 1289 locs->set_in(2, Location::Pair(Location::RequiresRegister(), | |
| 1290 Location::Any())); | |
| 1291 } | |
| 1292 break; | 1290 break; |
| 1293 case kTypedDataFloat32ArrayCid: | 1291 case kTypedDataFloat32ArrayCid: |
| 1294 case kTypedDataFloat64ArrayCid: | 1292 case kTypedDataFloat64ArrayCid: |
| 1295 // TODO(srdjan): Support Float64 constants. | 1293 // TODO(srdjan): Support Float64 constants. |
| 1296 locs->set_in(2, Location::RequiresFpuRegister()); | 1294 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1297 break; | 1295 break; |
| 1298 case kTypedDataInt32x4ArrayCid: | 1296 case kTypedDataInt32x4ArrayCid: |
| 1299 case kTypedDataFloat32x4ArrayCid: | 1297 case kTypedDataFloat32x4ArrayCid: |
| 1300 case kTypedDataFloat64x2ArrayCid: | 1298 case kTypedDataFloat64x2ArrayCid: |
| 1301 locs->set_in(2, Location::RequiresFpuRegister()); | 1299 locs->set_in(2, Location::RequiresFpuRegister()); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1382 } | 1380 } |
| 1383 case kTypedDataInt16ArrayCid: | 1381 case kTypedDataInt16ArrayCid: |
| 1384 case kTypedDataUint16ArrayCid: { | 1382 case kTypedDataUint16ArrayCid: { |
| 1385 Register value = locs()->in(2).reg(); | 1383 Register value = locs()->in(2).reg(); |
| 1386 __ SmiUntag(value); | 1384 __ SmiUntag(value); |
| 1387 __ movw(element_address, value); | 1385 __ movw(element_address, value); |
| 1388 break; | 1386 break; |
| 1389 } | 1387 } |
| 1390 case kTypedDataInt32ArrayCid: | 1388 case kTypedDataInt32ArrayCid: |
| 1391 case kTypedDataUint32ArrayCid: | 1389 case kTypedDataUint32ArrayCid: |
| 1392 if (value()->IsSmiValue()) { | 1390 __ movl(element_address, locs()->in(2).reg()); |
| 1393 ASSERT(RequiredInputRepresentation(2) == kTagged); | |
| 1394 Register value = locs()->in(2).reg(); | |
| 1395 __ SmiUntag(value); | |
| 1396 __ movl(element_address, value); | |
| 1397 } else { | |
| 1398 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | |
| 1399 PairLocation* value_pair = locs()->in(2).AsPairLocation(); | |
| 1400 Register value1 = value_pair->At(0).reg(); | |
| 1401 __ movl(element_address, value1); | |
| 1402 } | |
| 1403 break; | 1391 break; |
| 1404 case kTypedDataFloat32ArrayCid: | 1392 case kTypedDataFloat32ArrayCid: |
| 1405 __ movss(element_address, locs()->in(2).fpu_reg()); | 1393 __ movss(element_address, locs()->in(2).fpu_reg()); |
| 1406 break; | 1394 break; |
| 1407 case kTypedDataFloat64ArrayCid: | 1395 case kTypedDataFloat64ArrayCid: |
| 1408 __ movsd(element_address, locs()->in(2).fpu_reg()); | 1396 __ movsd(element_address, locs()->in(2).fpu_reg()); |
| 1409 break; | 1397 break; |
| 1410 case kTypedDataInt32x4ArrayCid: | 1398 case kTypedDataInt32x4ArrayCid: |
| 1411 case kTypedDataFloat32x4ArrayCid: | 1399 case kTypedDataFloat32x4ArrayCid: |
| 1412 case kTypedDataFloat64x2ArrayCid: | 1400 case kTypedDataFloat64x2ArrayCid: |
| (...skipping 4974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6387 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6375 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6388 Register out = locs()->out(0).reg(); | 6376 Register out = locs()->out(0).reg(); |
| 6389 ASSERT(locs()->in(0).reg() == out); | 6377 ASSERT(locs()->in(0).reg() == out); |
| 6390 | 6378 |
| 6391 ASSERT(op_kind() == Token::kBIT_NOT); | 6379 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6392 | 6380 |
| 6393 __ notl(out); | 6381 __ notl(out); |
| 6394 } | 6382 } |
| 6395 | 6383 |
| 6396 | 6384 |
| 6397 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate, | 6385 LocationSummary* BoxIntNInstr::MakeLocationSummary(Isolate* isolate, |
| 6398 bool opt) const { | |
| 6399 const intptr_t kNumInputs = 1; | |
| 6400 const intptr_t kNumTemps = 0; | |
| 6401 LocationSummary* summary = new(isolate) LocationSummary( | |
| 6402 isolate, | |
| 6403 kNumInputs, | |
| 6404 kNumTemps, | |
| 6405 ValueFitsSmi() ? LocationSummary::kNoCall | |
| 6406 : LocationSummary::kCallOnSlowPath); | |
| 6407 summary->set_in(0, Location::RequiresRegister()); | |
| 6408 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() | |
| 6409 : Location::RequiresRegister()); | |
| 6410 return summary; | |
| 6411 } | |
| 6412 | |
| 6413 | |
| 6414 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 6415 Register value = locs()->in(0).reg(); | |
| 6416 Register out = locs()->out(0).reg(); | |
| 6417 | |
| 6418 Label not_smi, done; | |
| 6419 | |
| 6420 if (ValueFitsSmi()) { | |
| 6421 ASSERT(value == out); | |
| 6422 __ SmiTag(value); | |
| 6423 } else { | |
| 6424 ASSERT(value != out); | |
| 6425 __ cmpl(value, Immediate(kSmiMax)); | |
| 6426 __ j(ABOVE, ¬_smi); | |
| 6427 // Smi. | |
| 6428 __ movl(out, value); | |
| 6429 __ SmiTag(out); | |
| 6430 __ jmp(&done); | |
| 6431 __ Bind(¬_smi); | |
| 6432 // Allocate a mint. | |
| 6433 BoxAllocationSlowPath::Allocate( | |
| 6434 compiler, this, compiler->mint_class(), out, kNoRegister); | |
| 6435 // Copy low word into mint. | |
| 6436 __ movl(FieldAddress(out, Mint::value_offset()), value); | |
| 6437 // Zero high word. | |
| 6438 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0)); | |
| 6439 __ Bind(&done); | |
| 6440 } | |
| 6441 } | |
| 6442 | |
| 6443 | |
| 6444 LocationSummary* BoxInt32Instr::MakeLocationSummary(Isolate* isolate, | |
| 6445 bool opt) const { | 6386 bool opt) const { |
| 6446 const intptr_t kNumInputs = 1; | 6387 const intptr_t kNumInputs = 1; |
| 6447 const intptr_t kNumTemps = 0; | 6388 const intptr_t kNumTemps = 0; |
| 6448 LocationSummary* summary = new(isolate) LocationSummary( | 6389 LocationSummary* summary = new(isolate) LocationSummary( |
| 6449 isolate, kNumInputs, kNumTemps, | 6390 isolate, kNumInputs, kNumTemps, |
| 6450 ValueFitsSmi() ? LocationSummary::kNoCall | 6391 ValueFitsSmi() ? LocationSummary::kNoCall |
| 6451 : LocationSummary::kCallOnSlowPath); | 6392 : LocationSummary::kCallOnSlowPath); |
| 6452 summary->set_in(0, ValueFitsSmi() ? Location::RequiresRegister() | 6393 const bool needs_writable_input = ValueFitsSmi() || |
| 6453 : Location::WritableRegister()); | 6394 (from_representation() == kUnboxedUint32); |
| 6395 summary->set_in(0, needs_writable_input ? Location::RequiresRegister() |
| 6396 : Location::WritableRegister()); |
| 6454 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() | 6397 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() |
| 6455 : Location::RequiresRegister()); | 6398 : Location::RequiresRegister()); |
| 6456 return summary; | 6399 return summary; |
| 6457 } | 6400 } |
| 6458 | 6401 |
| 6459 | 6402 |
| 6460 void BoxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6403 void BoxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6461 Register value = locs()->in(0).reg(); | 6404 const Register value = locs()->in(0).reg(); |
| 6462 Register out = locs()->out(0).reg(); | 6405 const Register out = locs()->out(0).reg(); |
| 6463 | 6406 |
| 6464 if (out != value) { | 6407 __ MoveRegister(out, value); |
| 6465 __ movl(out, value); | 6408 __ shll(out, Immediate(kSmiTagSize)); |
| 6466 } | |
| 6467 __ shll(out, Immediate(1)); | |
| 6468 if (!ValueFitsSmi()) { | 6409 if (!ValueFitsSmi()) { |
| 6469 Label done; | 6410 Label done; |
| 6470 __ j(NO_OVERFLOW, &done); | 6411 ASSERT(value != out); |
| 6412 if (from_representation() == kUnboxedInt32) { |
| 6413 __ j(NO_OVERFLOW, &done); |
| 6414 } else { |
| 6415 __ testl(value, Immediate(0xC0000000)); |
| 6416 __ j(ZERO, &done); |
| 6417 } |
| 6418 |
| 6471 // Allocate a mint. | 6419 // Allocate a mint. |
| 6472 // Value input is writable register and has to be manually preserved | 6420 // Value input is writable register and has to be manually preserved |
| 6473 // on the slow path. | 6421 // on the slow path. |
| 6474 locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32); | 6422 locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32); |
| 6475 BoxAllocationSlowPath::Allocate( | 6423 BoxAllocationSlowPath::Allocate( |
| 6476 compiler, this, compiler->mint_class(), out, kNoRegister); | 6424 compiler, this, compiler->mint_class(), out, kNoRegister); |
| 6477 __ movl(FieldAddress(out, Mint::value_offset()), value); | 6425 __ movl(FieldAddress(out, Mint::value_offset()), value); |
| 6478 __ sarl(value, Immediate(31)); // Sign extend. | 6426 if (from_representation() == kUnboxedInt32) { |
| 6479 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value); | 6427 __ sarl(value, Immediate(31)); // Sign extend. |
| 6428 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value); |
| 6429 } else { |
| 6430 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), |
| 6431 Immediate(0)); |
| 6432 } |
| 6480 __ Bind(&done); | 6433 __ Bind(&done); |
| 6481 } | 6434 } |
| 6482 } | 6435 } |
| 6483 | 6436 |
| 6484 | 6437 |
| 6485 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, | 6438 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate, |
| 6486 bool opt) const { | 6439 bool opt) const { |
| 6487 const intptr_t value_cid = value()->Type()->ToCid(); | 6440 const intptr_t value_cid = value()->Type()->ToCid(); |
| 6488 const intptr_t kNumInputs = 1; | 6441 const intptr_t kNumInputs = 1; |
| 6489 const intptr_t kNumTemps = | 6442 intptr_t kNumTemps = 0; |
| 6490 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; | 6443 |
| 6444 if (CanDeoptimize()) { |
| 6445 if ((value_cid != kSmiCid) && |
| 6446 (value_cid != kMintCid) && |
| 6447 !is_truncating()) { |
| 6448 kNumTemps = 2; |
| 6449 } else { |
| 6450 kNumTemps = 1; |
| 6451 } |
| 6452 } |
| 6453 |
| 6491 LocationSummary* summary = new(isolate) LocationSummary( | 6454 LocationSummary* summary = new(isolate) LocationSummary( |
| 6492 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6455 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6493 summary->set_in(0, Location::RequiresRegister()); | 6456 summary->set_in(0, Location::RequiresRegister()); |
| 6494 if (kNumTemps > 0) { | 6457 for (int i = 0; i < kNumTemps; i++) { |
| 6495 summary->set_temp(0, Location::RequiresRegister()); | 6458 summary->set_temp(i, Location::RequiresRegister()); |
| 6496 } | 6459 } |
| 6497 summary->set_out(0, Location::SameAsFirstInput()); | 6460 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid)) ? |
| 6498 return summary; | 6461 Location::SameAsFirstInput() : Location::RequiresRegister()); |
| 6499 } | |
| 6500 | |
| 6501 | |
| 6502 void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 6503 const intptr_t value_cid = value()->Type()->ToCid(); | |
| 6504 const Register value = locs()->in(0).reg(); | |
| 6505 ASSERT(value == locs()->out(0).reg()); | |
| 6506 | |
| 6507 // TODO(johnmccutchan): Emit better code for constant inputs. | |
| 6508 if (value_cid == kMintCid) { | |
| 6509 __ movl(value, FieldAddress(value, Mint::value_offset())); | |
| 6510 } else if (value_cid == kSmiCid) { | |
| 6511 __ SmiUntag(value); | |
| 6512 } else { | |
| 6513 Register temp = locs()->temp(0).reg(); | |
| 6514 Label* deopt = compiler->AddDeoptStub(deopt_id_, | |
| 6515 ICData::kDeoptUnboxInteger); | |
| 6516 Label is_smi, done; | |
| 6517 __ testl(value, Immediate(kSmiTagMask)); | |
| 6518 __ j(ZERO, &is_smi); | |
| 6519 __ CompareClassId(value, kMintCid, temp); | |
| 6520 __ j(NOT_EQUAL, deopt); | |
| 6521 __ movl(value, FieldAddress(value, Mint::value_offset())); | |
| 6522 __ jmp(&done); | |
| 6523 __ Bind(&is_smi); | |
| 6524 __ SmiUntag(value); | |
| 6525 __ Bind(&done); | |
| 6526 } | |
| 6527 } | |
| 6528 | |
| 6529 | |
| 6530 LocationSummary* UnboxInt32Instr::MakeLocationSummary(Isolate* isolate, | |
| 6531 bool opt) const { | |
| 6532 const intptr_t value_cid = value()->Type()->ToCid(); | |
| 6533 const intptr_t kNumInputs = 1; | |
| 6534 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | |
| 6535 LocationSummary* summary = new(isolate) LocationSummary( | |
| 6536 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 6537 summary->set_in(0, Location::RequiresRegister()); | |
| 6538 if (kNumTemps > 0) { | |
| 6539 summary->set_temp(0, Location::RequiresRegister()); | |
| 6540 } | |
| 6541 summary->set_out(0, (value_cid == kSmiCid) ? Location::SameAsFirstInput() | |
| 6542 : Location::RequiresRegister()); | |
| 6543 return summary; | 6462 return summary; |
| 6544 } | 6463 } |
| 6545 | 6464 |
| 6546 | 6465 |
| 6547 static void LoadInt32FromMint(FlowGraphCompiler* compiler, | 6466 static void LoadInt32FromMint(FlowGraphCompiler* compiler, |
| 6548 Register mint, | |
| 6549 Register result, | 6467 Register result, |
| 6468 const Address& lo, |
| 6469 const Address& hi, |
| 6550 Register temp, | 6470 Register temp, |
| 6551 Label* deopt) { | 6471 Label* deopt) { |
| 6552 __ movl(result, FieldAddress(mint, Mint::value_offset())); | 6472 __ movl(result, lo); |
| 6553 if (deopt != NULL) { | 6473 if (deopt != NULL) { |
| 6474 ASSERT(temp != result); |
| 6554 __ movl(temp, result); | 6475 __ movl(temp, result); |
| 6555 __ sarl(temp, Immediate(31)); | 6476 __ sarl(temp, Immediate(31)); |
| 6556 __ cmpl(temp, FieldAddress(mint, Mint::value_offset() + kWordSize)); | 6477 __ cmpl(temp, hi); |
| 6557 __ j(NOT_EQUAL, deopt); | 6478 __ j(NOT_EQUAL, deopt); |
| 6558 } | 6479 } |
| 6559 } | 6480 } |
| 6560 | 6481 |
| 6561 | 6482 |
| 6562 void UnboxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6483 void UnboxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6563 const intptr_t value_cid = value()->Type()->ToCid(); | 6484 const intptr_t value_cid = value()->Type()->ToCid(); |
| 6564 const Register value = locs()->in(0).reg(); | 6485 Register value = locs()->in(0).reg(); |
| 6565 const Register result = locs()->out(0).reg(); | 6486 const Register result = locs()->out(0).reg(); |
| 6487 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; |
| 6488 Label* deopt = CanDeoptimize() ? |
| 6489 compiler->AddDeoptStub(deopt_id_, ICData::kDeoptUnboxInteger) : NULL; |
| 6490 Label* out_of_range = !is_truncating() ? deopt : NULL; |
| 6566 | 6491 |
| 6567 // TODO(johnmccutchan): Emit better code for constant inputs. | 6492 const intptr_t lo_offset = Mint::value_offset(); |
| 6568 if (value_cid == kMintCid) { | 6493 const intptr_t hi_offset = Mint::value_offset() + kWordSize; |
| 6569 Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; | 6494 |
| 6570 Label* deopt = CanDeoptimize() ? | 6495 if (value_cid == kSmiCid) { |
| 6571 compiler->AddDeoptStub(deopt_id_, ICData::kDeoptUnboxInteger) : NULL; | |
| 6572 LoadInt32FromMint(compiler, | |
| 6573 value, | |
| 6574 result, | |
| 6575 temp, | |
| 6576 deopt); | |
| 6577 } else if (value_cid == kSmiCid) { | |
| 6578 ASSERT(value == result); | 6496 ASSERT(value == result); |
| 6579 __ SmiUntag(value); | 6497 __ SmiUntag(value); |
| 6498 } else if (value_cid == kMintCid) { |
| 6499 ASSERT((value != result) || (out_of_range == NULL)); |
| 6500 LoadInt32FromMint(compiler, |
| 6501 result, |
| 6502 FieldAddress(value, lo_offset), |
| 6503 FieldAddress(value, hi_offset), |
| 6504 temp, |
| 6505 out_of_range); |
| 6580 } else { | 6506 } else { |
| 6581 Register temp = locs()->temp(0).reg(); | 6507 ASSERT(value == result); |
| 6582 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 6508 Label done; |
| 6583 ICData::kDeoptUnboxInteger); | 6509 __ SmiUntagOrCheckClass(value, kMintCid, temp, &done); |
| 6584 Label is_smi, done; | |
| 6585 __ testl(value, Immediate(kSmiTagMask)); | |
| 6586 __ j(ZERO, &is_smi); | |
| 6587 __ CompareClassId(value, kMintCid, temp); | |
| 6588 __ j(NOT_EQUAL, deopt); | 6510 __ j(NOT_EQUAL, deopt); |
| 6511 if (out_of_range != NULL) { |
| 6512 Register value_temp = locs()->temp(1).reg(); |
| 6513 __ movl(value_temp, value); |
| 6514 value = value_temp; |
| 6515 } |
| 6589 LoadInt32FromMint(compiler, | 6516 LoadInt32FromMint(compiler, |
| 6590 value, | |
| 6591 result, | 6517 result, |
| 6518 Address(value, TIMES_2, lo_offset), |
| 6519 Address(value, TIMES_2, hi_offset), |
| 6592 temp, | 6520 temp, |
| 6593 deopt); | 6521 out_of_range); |
| 6594 __ movl(value, FieldAddress(value, Mint::value_offset())); | |
| 6595 __ jmp(&done); | |
| 6596 __ Bind(&is_smi); | |
| 6597 __ SmiUntag(value); | |
| 6598 __ Bind(&done); | 6522 __ Bind(&done); |
| 6599 } | 6523 } |
| 6600 } | 6524 } |
| 6601 | 6525 |
| 6602 | 6526 |
| 6603 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | 6527 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 6604 bool opt) const { | 6528 bool opt) const { |
| 6605 const intptr_t kNumInputs = 1; | 6529 const intptr_t kNumInputs = 1; |
| 6606 const intptr_t kNumTemps = 0; | 6530 const intptr_t kNumTemps = 0; |
| 6607 LocationSummary* summary = new(isolate) LocationSummary( | 6531 LocationSummary* summary = new(isolate) LocationSummary( |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7037 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6961 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
| 7038 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6962 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
| 7039 #endif | 6963 #endif |
| 7040 } | 6964 } |
| 7041 | 6965 |
| 7042 } // namespace dart | 6966 } // namespace dart |
| 7043 | 6967 |
| 7044 #undef __ | 6968 #undef __ |
| 7045 | 6969 |
| 7046 #endif // defined TARGET_ARCH_IA32 | 6970 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |