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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 5949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5960 if (!is_smi()) { | 5960 if (!is_smi()) { |
5961 summary->set_temp(0, Location::RequiresRegister()); | 5961 summary->set_temp(0, Location::RequiresRegister()); |
5962 } | 5962 } |
5963 summary->set_out(0, Location::RequiresRegister()); | 5963 summary->set_out(0, Location::RequiresRegister()); |
5964 return summary; | 5964 return summary; |
5965 } | 5965 } |
5966 | 5966 |
5967 | 5967 |
5968 class BoxIntegerSlowPath : public SlowPathCode { | 5968 class BoxIntegerSlowPath : public SlowPathCode { |
5969 public: | 5969 public: |
5970 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) | 5970 explicit BoxIntegerSlowPath(Definition* instruction) |
5971 : instruction_(instruction) { } | 5971 : instruction_(instruction) { } |
5972 | 5972 |
5973 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5973 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
5974 __ Comment("BoxIntegerSlowPath"); | 5974 __ Comment("BoxIntegerSlowPath"); |
5975 __ Bind(entry_label()); | 5975 __ Bind(entry_label()); |
5976 Isolate* isolate = compiler->isolate(); | 5976 Isolate* isolate = compiler->isolate(); |
5977 StubCode* stub_code = isolate->stub_code(); | 5977 StubCode* stub_code = isolate->stub_code(); |
5978 const Class& mint_class = | 5978 const Class& mint_class = |
5979 Class::ZoneHandle(isolate->object_store()->mint_class()); | 5979 Class::ZoneHandle(isolate->object_store()->mint_class()); |
5980 const Code& stub = | 5980 const Code& stub = |
5981 Code::Handle(isolate, stub_code->GetAllocationStubForClass(mint_class)); | 5981 Code::Handle(isolate, stub_code->GetAllocationStubForClass(mint_class)); |
5982 const ExternalLabel label(stub.EntryPoint()); | 5982 const ExternalLabel label(stub.EntryPoint()); |
5983 | 5983 |
5984 LocationSummary* locs = instruction_->locs(); | 5984 LocationSummary* locs = instruction_->locs(); |
5985 ASSERT(!locs->live_registers()->Contains(locs->out(0))); | 5985 ASSERT(!locs->live_registers()->Contains(locs->out(0))); |
5986 | 5986 |
5987 compiler->SaveLiveRegisters(locs); | 5987 compiler->SaveLiveRegisters(locs); |
5988 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 5988 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
5989 &label, | 5989 &label, |
5990 RawPcDescriptors::kOther, | 5990 RawPcDescriptors::kOther, |
5991 locs); | 5991 locs); |
5992 __ mov(locs->out(0).reg(), Operand(R0)); | 5992 __ mov(locs->out(0).reg(), Operand(R0)); |
5993 compiler->RestoreLiveRegisters(locs); | 5993 compiler->RestoreLiveRegisters(locs); |
5994 | 5994 |
5995 __ b(exit_label()); | 5995 __ b(exit_label()); |
5996 } | 5996 } |
5997 | 5997 |
5998 private: | 5998 private: |
5999 BoxIntegerInstr* instruction_; | 5999 Definition* instruction_; |
6000 }; | 6000 }; |
6001 | 6001 |
6002 | 6002 |
6003 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6003 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6004 if (is_smi()) { | 6004 if (is_smi()) { |
6005 PairLocation* value_pair = locs()->in(0).AsPairLocation(); | 6005 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
6006 Register value_lo = value_pair->At(0).reg(); | 6006 Register value_lo = value_pair->At(0).reg(); |
6007 Register out_reg = locs()->out(0).reg(); | 6007 Register out_reg = locs()->out(0).reg(); |
6008 __ mov(out_reg, Operand(value_lo)); | 6008 __ mov(out_reg, Operand(value_lo)); |
6009 __ SmiTag(out_reg); | 6009 __ SmiTag(out_reg); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6266 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | 6266 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); |
6267 } | 6267 } |
6268 __ mvn(out_lo, Operand(left_lo)); | 6268 __ mvn(out_lo, Operand(left_lo)); |
6269 __ mvn(out_hi, Operand(left_hi)); | 6269 __ mvn(out_hi, Operand(left_hi)); |
6270 if (FLAG_throw_on_javascript_int_overflow) { | 6270 if (FLAG_throw_on_javascript_int_overflow) { |
6271 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); | 6271 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); |
6272 } | 6272 } |
6273 } | 6273 } |
6274 | 6274 |
6275 | 6275 |
| 6276 CompileType BinaryUint32OpInstr::ComputeType() const { |
| 6277 return CompileType::Int(); |
| 6278 } |
| 6279 |
| 6280 |
| 6281 CompileType ShiftUint32OpInstr::ComputeType() const { |
| 6282 return CompileType::Int(); |
| 6283 } |
| 6284 |
| 6285 |
| 6286 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 6287 return CompileType::Int(); |
| 6288 } |
| 6289 |
| 6290 |
| 6291 CompileType BoxUint32Instr::ComputeType() const { |
| 6292 return CompileType::Int(); |
| 6293 } |
| 6294 |
| 6295 |
| 6296 CompileType UnboxUint32Instr::ComputeType() const { |
| 6297 return CompileType::Int(); |
| 6298 } |
| 6299 |
| 6300 |
| 6301 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 6302 bool opt) const { |
| 6303 const intptr_t kNumInputs = 2; |
| 6304 const intptr_t kNumTemps = 0; |
| 6305 LocationSummary* summary = new(isolate) LocationSummary( |
| 6306 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6307 summary->set_in(0, Location::RequiresRegister()); |
| 6308 summary->set_in(1, Location::RequiresRegister()); |
| 6309 summary->set_out(0, Location::RequiresRegister()); |
| 6310 return summary; |
| 6311 } |
| 6312 |
| 6313 |
| 6314 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6315 Register left = locs()->in(0).reg(); |
| 6316 Register right = locs()->in(1).reg(); |
| 6317 Register out = locs()->out(0).reg(); |
| 6318 ASSERT(out != left); |
| 6319 switch (op_kind()) { |
| 6320 case Token::kBIT_AND: |
| 6321 __ and_(out, left, Operand(right)); |
| 6322 break; |
| 6323 case Token::kBIT_OR: |
| 6324 __ orr(out, left, Operand(right)); |
| 6325 break; |
| 6326 case Token::kBIT_XOR: |
| 6327 __ eor(out, left, Operand(right)); |
| 6328 break; |
| 6329 case Token::kADD: |
| 6330 __ add(out, left, Operand(right)); |
| 6331 break; |
| 6332 case Token::kSUB: |
| 6333 __ sub(out, left, Operand(right)); |
| 6334 break; |
| 6335 default: |
| 6336 UNREACHABLE(); |
| 6337 } |
| 6338 } |
| 6339 |
| 6340 |
| 6341 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 6342 bool opt) const { |
| 6343 const intptr_t kNumInputs = 2; |
| 6344 const intptr_t kNumTemps = 1; |
| 6345 LocationSummary* summary = new(isolate) LocationSummary( |
| 6346 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6347 summary->set_in(0, Location::RequiresRegister()); |
| 6348 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 6349 summary->set_temp(0, Location::RequiresRegister()); |
| 6350 summary->set_out(0, Location::RequiresRegister()); |
| 6351 return summary; |
| 6352 } |
| 6353 |
| 6354 |
| 6355 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6356 const intptr_t kShifterLimit = 31; |
| 6357 |
| 6358 Register left = locs()->in(0).reg(); |
| 6359 Register out = locs()->out(0).reg(); |
| 6360 Register temp = locs()->temp(0).reg(); |
| 6361 |
| 6362 ASSERT(left != out); |
| 6363 |
| 6364 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 6365 |
| 6366 if (locs()->in(1).IsConstant()) { |
| 6367 // Shifter is constant. |
| 6368 |
| 6369 const Object& constant = locs()->in(1).constant(); |
| 6370 ASSERT(constant.IsSmi()); |
| 6371 const intptr_t shift_value = Smi::Cast(constant).Value(); |
| 6372 |
| 6373 // Check constant shift value. |
| 6374 if (shift_value == 0) { |
| 6375 // Nothing to do. |
| 6376 __ mov(out, Operand(left)); |
| 6377 } else if (shift_value < 0) { |
| 6378 // Invalid shift value. |
| 6379 __ b(deopt); |
| 6380 } else if (shift_value > kShifterLimit) { |
| 6381 // Result is 0. |
| 6382 __ eor(out, out, Operand(out)); |
| 6383 } else { |
| 6384 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
| 6385 switch (op_kind()) { |
| 6386 case Token::kSHR: |
| 6387 __ Lsr(out, left, shift_value); |
| 6388 break; |
| 6389 case Token::kSHL: |
| 6390 __ Lsl(out, left, shift_value); |
| 6391 break; |
| 6392 default: |
| 6393 UNREACHABLE(); |
| 6394 } |
| 6395 } |
| 6396 return; |
| 6397 } |
| 6398 |
| 6399 // Non constant shift value. |
| 6400 |
| 6401 Register shifter = locs()->in(1).reg(); |
| 6402 |
| 6403 __ mov(temp, Operand(shifter)); |
| 6404 __ SmiUntag(temp); |
| 6405 __ CompareImmediate(temp, 0); |
| 6406 // If shift value is < 0, deoptimize. |
| 6407 __ b(deopt, LT); |
| 6408 __ CompareImmediate(temp, kShifterLimit); |
| 6409 // > kShifterLimit, result is 0. |
| 6410 __ eor(out, out, Operand(out), HI); |
| 6411 // Do the shift. |
| 6412 switch (op_kind()) { |
| 6413 case Token::kSHR: |
| 6414 __ Lsr(out, left, temp, LS); |
| 6415 break; |
| 6416 case Token::kSHL: |
| 6417 __ Lsl(out, left, temp, LS); |
| 6418 break; |
| 6419 default: |
| 6420 UNREACHABLE(); |
| 6421 } |
| 6422 } |
| 6423 |
| 6424 |
| 6425 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 6426 bool opt) const { |
| 6427 const intptr_t kNumInputs = 1; |
| 6428 const intptr_t kNumTemps = 0; |
| 6429 LocationSummary* summary = new(isolate) LocationSummary( |
| 6430 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6431 summary->set_in(0, Location::RequiresRegister()); |
| 6432 summary->set_out(0, Location::RequiresRegister()); |
| 6433 return summary; |
| 6434 } |
| 6435 |
| 6436 |
| 6437 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6438 Register left = locs()->in(0).reg(); |
| 6439 Register out = locs()->out(0).reg(); |
| 6440 ASSERT(left != out); |
| 6441 |
| 6442 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6443 |
| 6444 __ mvn(out, Operand(left)); |
| 6445 } |
| 6446 |
| 6447 |
| 6448 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate, |
| 6449 bool opt) const { |
| 6450 const intptr_t kNumInputs = 1; |
| 6451 const intptr_t kNumTemps = 1; |
| 6452 LocationSummary* summary = new(isolate) LocationSummary( |
| 6453 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 6454 summary->set_in(0, Location::RequiresRegister()); |
| 6455 summary->set_temp(0, Location::RequiresRegister()); |
| 6456 summary->set_out(0, Location::RequiresRegister()); |
| 6457 return summary; |
| 6458 } |
| 6459 |
| 6460 |
| 6461 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6462 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
| 6463 compiler->AddSlowPathCode(slow_path); |
| 6464 Register value = locs()->in(0).reg(); |
| 6465 Register out = locs()->out(0).reg(); |
| 6466 Register temp = locs()->temp(0).reg(); |
| 6467 ASSERT(value != out); |
| 6468 |
| 6469 Label not_smi, done; |
| 6470 |
| 6471 // TODO(johnmccutchan): Use range information to fast path smi / mint boxing. |
| 6472 |
| 6473 // Test if this value is <= kSmiMax. |
| 6474 __ CompareImmediate(value, kSmiMax); |
| 6475 __ b(¬_smi, HI); |
| 6476 // Smi. |
| 6477 __ mov(out, Operand(value)); |
| 6478 __ SmiTag(out); |
| 6479 __ b(&done); |
| 6480 __ Bind(¬_smi); |
| 6481 // Allocate a mint. |
| 6482 __ TryAllocate( |
| 6483 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), |
| 6484 slow_path->entry_label(), |
| 6485 out, |
| 6486 temp); |
| 6487 __ Bind(slow_path->exit_label()); |
| 6488 // Copy low word into mint. |
| 6489 __ StoreToOffset(kWord, |
| 6490 value, |
| 6491 out, |
| 6492 Mint::value_offset() - kHeapObjectTag); |
| 6493 // Zero high word. |
| 6494 __ eor(temp, temp, Operand(temp)); |
| 6495 __ StoreToOffset(kWord, |
| 6496 temp, |
| 6497 out, |
| 6498 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 6499 __ Bind(&done); |
| 6500 } |
| 6501 |
| 6502 |
| 6503 |
| 6504 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, |
| 6505 bool opt) const { |
| 6506 const intptr_t value_cid = value()->Type()->ToCid(); |
| 6507 const intptr_t kNumInputs = 1; |
| 6508 const intptr_t kNumTemps = |
| 6509 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; |
| 6510 LocationSummary* summary = new(isolate) LocationSummary( |
| 6511 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6512 summary->set_in(0, Location::RequiresRegister()); |
| 6513 if (kNumTemps > 0) { |
| 6514 summary->set_temp(0, Location::RequiresRegister()); |
| 6515 } |
| 6516 summary->set_out(0, Location::RequiresRegister()); |
| 6517 return summary; |
| 6518 } |
| 6519 |
| 6520 |
| 6521 void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6522 const intptr_t value_cid = value()->Type()->ToCid(); |
| 6523 const Register value = locs()->in(0).reg(); |
| 6524 const Register out = locs()->out(0).reg(); |
| 6525 ASSERT(value != out); |
| 6526 |
| 6527 // TODO(johnmccutchan): Emit better code for constant inputs. |
| 6528 if (value_cid == kMintCid) { |
| 6529 __ LoadFromOffset(kWord, out, value, Mint::value_offset() - kHeapObjectTag); |
| 6530 } else if (value_cid == kSmiCid) { |
| 6531 __ mov(out, Operand(value)); |
| 6532 __ SmiUntag(out); |
| 6533 } else { |
| 6534 Register temp = locs()->temp(0).reg(); |
| 6535 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
| 6536 ICData::kDeoptUnboxInteger); |
| 6537 Label done; |
| 6538 __ tst(value, Operand(kSmiTagMask)); |
| 6539 // Smi case. |
| 6540 __ mov(out, Operand(value), EQ); |
| 6541 __ SmiUntag(out, EQ); |
| 6542 __ b(&done, EQ); |
| 6543 // Mint case. |
| 6544 __ CompareClassId(value, kMintCid, temp); |
| 6545 __ b(deopt, NE); |
| 6546 __ LoadFromOffset(kWord, out, value, Mint::value_offset() - kHeapObjectTag); |
| 6547 __ Bind(&done); |
| 6548 } |
| 6549 } |
| 6550 |
| 6551 |
| 6552 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 6553 bool opt) const { |
| 6554 const intptr_t kNumInputs = 1; |
| 6555 const intptr_t kNumTemps = 0; |
| 6556 LocationSummary* summary = new(isolate) LocationSummary( |
| 6557 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6558 if (from() == kUnboxedMint) { |
| 6559 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6560 Location::RequiresRegister())); |
| 6561 summary->set_out(0, Location::RequiresRegister()); |
| 6562 } else { |
| 6563 ASSERT(from() == kUnboxedUint32); |
| 6564 summary->set_in(0, Location::RequiresRegister()); |
| 6565 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 6566 Location::RequiresRegister())); |
| 6567 } |
| 6568 return summary; |
| 6569 } |
| 6570 |
| 6571 |
| 6572 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6573 if (from() == kUnboxedMint) { |
| 6574 PairLocation* in_pair = locs()->in(0).AsPairLocation(); |
| 6575 Register in_lo = in_pair->At(0).reg(); |
| 6576 Register out = locs()->out(0).reg(); |
| 6577 // Copy low word. |
| 6578 __ mov(out, Operand(in_lo)); |
| 6579 } else { |
| 6580 ASSERT(from() == kUnboxedUint32); |
| 6581 Register in = locs()->in(0).reg(); |
| 6582 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 6583 Register out_lo = out_pair->At(0).reg(); |
| 6584 Register out_hi = out_pair->At(1).reg(); |
| 6585 // Copy low word. |
| 6586 __ mov(out_lo, Operand(in)); |
| 6587 // Zero upper word. |
| 6588 __ eor(out_hi, out_hi, Operand(out_hi)); |
| 6589 } |
| 6590 } |
| 6591 |
| 6592 |
6276 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6593 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
6277 bool opt) const { | 6594 bool opt) const { |
6278 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6595 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
6279 } | 6596 } |
6280 | 6597 |
6281 | 6598 |
6282 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6599 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6283 compiler->GenerateRuntimeCall(token_pos(), | 6600 compiler->GenerateRuntimeCall(token_pos(), |
6284 deopt_id(), | 6601 deopt_id(), |
6285 kThrowRuntimeEntry, | 6602 kThrowRuntimeEntry, |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6501 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 6818 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
6502 #if defined(DEBUG) | 6819 #if defined(DEBUG) |
6503 __ LoadImmediate(R4, kInvalidObjectPointer); | 6820 __ LoadImmediate(R4, kInvalidObjectPointer); |
6504 __ LoadImmediate(R5, kInvalidObjectPointer); | 6821 __ LoadImmediate(R5, kInvalidObjectPointer); |
6505 #endif | 6822 #endif |
6506 } | 6823 } |
6507 | 6824 |
6508 } // namespace dart | 6825 } // namespace dart |
6509 | 6826 |
6510 #endif // defined TARGET_ARCH_ARM | 6827 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |