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 5907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5918 if (!is_smi()) { | 5918 if (!is_smi()) { |
5919 summary->set_temp(0, Location::RequiresRegister()); | 5919 summary->set_temp(0, Location::RequiresRegister()); |
5920 } | 5920 } |
5921 summary->set_out(0, Location::RequiresRegister()); | 5921 summary->set_out(0, Location::RequiresRegister()); |
5922 return summary; | 5922 return summary; |
5923 } | 5923 } |
5924 | 5924 |
5925 | 5925 |
5926 class BoxIntegerSlowPath : public SlowPathCode { | 5926 class BoxIntegerSlowPath : public SlowPathCode { |
5927 public: | 5927 public: |
5928 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) | 5928 explicit BoxIntegerSlowPath(Definition* instruction) |
5929 : instruction_(instruction) { } | 5929 : instruction_(instruction) { } |
5930 | 5930 |
5931 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5931 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
5932 __ Comment("BoxIntegerSlowPath"); | 5932 __ Comment("BoxIntegerSlowPath"); |
5933 __ Bind(entry_label()); | 5933 __ Bind(entry_label()); |
5934 Isolate* isolate = compiler->isolate(); | 5934 Isolate* isolate = compiler->isolate(); |
5935 StubCode* stub_code = isolate->stub_code(); | 5935 StubCode* stub_code = isolate->stub_code(); |
5936 const Class& mint_class = | 5936 const Class& mint_class = |
5937 Class::ZoneHandle(isolate->object_store()->mint_class()); | 5937 Class::ZoneHandle(isolate->object_store()->mint_class()); |
5938 const Code& stub = | 5938 const Code& stub = |
5939 Code::Handle(isolate, stub_code->GetAllocationStubForClass(mint_class)); | 5939 Code::Handle(isolate, stub_code->GetAllocationStubForClass(mint_class)); |
5940 const ExternalLabel label(stub.EntryPoint()); | 5940 const ExternalLabel label(stub.EntryPoint()); |
5941 | 5941 |
5942 LocationSummary* locs = instruction_->locs(); | 5942 LocationSummary* locs = instruction_->locs(); |
5943 ASSERT(!locs->live_registers()->Contains(locs->out(0))); | 5943 ASSERT(!locs->live_registers()->Contains(locs->out(0))); |
5944 | 5944 |
5945 compiler->SaveLiveRegisters(locs); | 5945 compiler->SaveLiveRegisters(locs); |
5946 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 5946 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
5947 &label, | 5947 &label, |
5948 RawPcDescriptors::kOther, | 5948 RawPcDescriptors::kOther, |
5949 locs); | 5949 locs); |
5950 __ mov(locs->out(0).reg(), Operand(R0)); | 5950 __ mov(locs->out(0).reg(), Operand(R0)); |
5951 compiler->RestoreLiveRegisters(locs); | 5951 compiler->RestoreLiveRegisters(locs); |
5952 | 5952 |
5953 __ b(exit_label()); | 5953 __ b(exit_label()); |
5954 } | 5954 } |
5955 | 5955 |
5956 private: | 5956 private: |
5957 BoxIntegerInstr* instruction_; | 5957 Definition* instruction_; |
5958 }; | 5958 }; |
5959 | 5959 |
5960 | 5960 |
5961 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5961 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5962 if (is_smi()) { | 5962 if (is_smi()) { |
5963 PairLocation* value_pair = locs()->in(0).AsPairLocation(); | 5963 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
5964 Register value_lo = value_pair->At(0).reg(); | 5964 Register value_lo = value_pair->At(0).reg(); |
5965 Register out_reg = locs()->out(0).reg(); | 5965 Register out_reg = locs()->out(0).reg(); |
5966 __ mov(out_reg, Operand(value_lo)); | 5966 __ mov(out_reg, Operand(value_lo)); |
5967 __ SmiTag(out_reg); | 5967 __ SmiTag(out_reg); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6224 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | 6224 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); |
6225 } | 6225 } |
6226 __ mvn(out_lo, Operand(left_lo)); | 6226 __ mvn(out_lo, Operand(left_lo)); |
6227 __ mvn(out_hi, Operand(left_hi)); | 6227 __ mvn(out_hi, Operand(left_hi)); |
6228 if (FLAG_throw_on_javascript_int_overflow) { | 6228 if (FLAG_throw_on_javascript_int_overflow) { |
6229 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); | 6229 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); |
6230 } | 6230 } |
6231 } | 6231 } |
6232 | 6232 |
6233 | 6233 |
6234 CompileType BinaryUint32OpInstr::ComputeType() const { | |
6235 return CompileType::Int(); | |
6236 } | |
6237 | |
6238 | |
6239 CompileType ShiftUint32OpInstr::ComputeType() const { | |
6240 return CompileType::Int(); | |
6241 } | |
6242 | |
6243 | |
6244 CompileType UnaryUint32OpInstr::ComputeType() const { | |
6245 return CompileType::Int(); | |
6246 } | |
6247 | |
6248 | |
6249 CompileType BoxUint32Instr::ComputeType() const { | |
6250 return CompileType::Int(); | |
6251 } | |
6252 | |
6253 | |
6254 CompileType UnboxUint32Instr::ComputeType() const { | |
6255 return CompileType::Int(); | |
6256 } | |
6257 | |
6258 | |
6259 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, | |
6260 bool opt) const { | |
6261 const intptr_t kNumInputs = 2; | |
6262 const intptr_t kNumTemps = 0; | |
6263 LocationSummary* summary = new(isolate) LocationSummary( | |
6264 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
6265 summary->set_in(0, Location::RequiresRegister()); | |
6266 summary->set_in(1, Location::RequiresRegister()); | |
6267 summary->set_out(0, Location::RequiresRegister()); | |
6268 return summary; | |
6269 } | |
6270 | |
6271 | |
6272 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6273 Register left = locs()->in(0).reg(); | |
6274 Register right = locs()->in(1).reg(); | |
6275 Register out = locs()->out(0).reg(); | |
6276 ASSERT(out != left); | |
6277 switch (op_kind()) { | |
6278 case Token::kBIT_AND: | |
6279 __ and_(out, left, Operand(right)); | |
6280 break; | |
6281 case Token::kBIT_OR: | |
6282 __ orr(out, left, Operand(right)); | |
6283 break; | |
6284 case Token::kBIT_XOR: | |
6285 __ eor(out, left, Operand(right)); | |
6286 break; | |
6287 case Token::kADD: | |
6288 __ add(out, left, Operand(right)); | |
6289 break; | |
6290 case Token::kSUB: | |
6291 __ sub(out, left, Operand(right)); | |
6292 break; | |
6293 default: | |
6294 UNREACHABLE(); | |
6295 } | |
6296 } | |
6297 | |
6298 | |
6299 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, | |
6300 bool opt) const { | |
6301 const intptr_t kNumInputs = 2; | |
6302 const intptr_t kNumTemps = 1; | |
6303 LocationSummary* summary = new(isolate) LocationSummary( | |
6304 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
6305 summary->set_in(0, Location::RequiresRegister()); | |
6306 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | |
6307 summary->set_temp(0, Location::RequiresRegister()); | |
6308 summary->set_out(0, Location::RequiresRegister()); | |
6309 return summary; | |
6310 } | |
6311 | |
6312 | |
6313 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6314 const intptr_t kShifterLimit = 31; | |
6315 | |
6316 Register left = locs()->in(0).reg(); | |
6317 Register out = locs()->out(0).reg(); | |
6318 Register temp = locs()->temp(0).reg(); | |
6319 | |
6320 ASSERT(left != out); | |
6321 | |
6322 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | |
6323 | |
6324 if (locs()->in(1).IsConstant()) { | |
6325 // Shifter is constant. | |
6326 | |
6327 const Object& constant = locs()->in(1).constant(); | |
6328 ASSERT(constant.IsSmi()); | |
6329 const intptr_t shift_value = Smi::Cast(constant).Value(); | |
6330 | |
6331 // Check constant shift value. | |
6332 if (shift_value == 0) { | |
6333 // Nothing to do. | |
zra
2014/07/11 15:45:05
Move in to out. They can be different registers. o
Cutch
2014/07/11 22:04:14
Good catch. I forgot to perform the move in this c
| |
6334 } else if (shift_value < 0) { | |
6335 // Invalid shift value. | |
6336 __ b(deopt); | |
6337 } else if (shift_value > kShifterLimit) { | |
6338 // Result is 0. | |
6339 __ eor(out, out, Operand(out)); | |
6340 } else { | |
6341 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | |
6342 switch (op_kind()) { | |
6343 case Token::kSHR: | |
6344 __ Lsr(out, left, shift_value); | |
6345 break; | |
6346 case Token::kSHL: | |
6347 __ Lsl(out, left, shift_value); | |
6348 break; | |
6349 default: | |
6350 UNREACHABLE(); | |
6351 } | |
6352 } | |
6353 return; | |
6354 } | |
6355 | |
6356 // Non constant shift value. | |
6357 | |
6358 Register shifter = locs()->in(1).reg(); | |
6359 | |
6360 Label done; | |
6361 Label zero; | |
6362 | |
6363 __ mov(temp, Operand(shifter)); | |
6364 __ SmiUntag(temp); | |
6365 __ CompareImmediate(temp, 0); | |
6366 // If shift value is < 0, deoptimize. | |
6367 __ b(deopt, LT); | |
6368 __ CompareImmediate(temp, kShifterLimit); | |
zra
2014/07/11 15:45:05
With conditional ops:
__ CompareImmediate(temp, k
Cutch
2014/07/11 22:04:14
Done.
| |
6369 // If shift value is >= 32, return zero. | |
6370 __ b(&zero, HI); | |
6371 | |
6372 // Do the shift. | |
6373 switch (op_kind()) { | |
6374 case Token::kSHR: | |
6375 __ Lsr(out, left, temp); | |
6376 __ b(&done); | |
6377 break; | |
6378 case Token::kSHL: | |
6379 __ Lsl(out, left, temp); | |
6380 __ b(&done); | |
6381 break; | |
6382 default: | |
6383 UNREACHABLE(); | |
6384 } | |
6385 | |
6386 __ Bind(&zero); | |
6387 // Shift was greater than 31 bits, just return zero. | |
6388 __ eor(out, out, Operand(out)); | |
6389 | |
6390 // Exit path. | |
6391 __ Bind(&done); | |
6392 } | |
6393 | |
6394 | |
6395 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, | |
6396 bool opt) const { | |
6397 const intptr_t kNumInputs = 1; | |
6398 const intptr_t kNumTemps = 0; | |
6399 LocationSummary* summary = new(isolate) LocationSummary( | |
6400 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
6401 summary->set_in(0, Location::RequiresRegister()); | |
6402 summary->set_out(0, Location::RequiresRegister()); | |
6403 return summary; | |
6404 } | |
6405 | |
6406 | |
6407 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6408 Register left = locs()->in(0).reg(); | |
6409 Register out = locs()->out(0).reg(); | |
6410 ASSERT(left != out); | |
6411 | |
6412 ASSERT(op_kind() == Token::kBIT_NOT); | |
6413 | |
6414 __ mvn(out, Operand(left)); | |
6415 } | |
6416 | |
6417 | |
6418 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate, | |
6419 bool opt) const { | |
6420 const intptr_t kNumInputs = 1; | |
6421 const intptr_t kNumTemps = 1; | |
6422 LocationSummary* summary = new(isolate) LocationSummary( | |
6423 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | |
6424 summary->set_in(0, Location::RequiresRegister()); | |
6425 summary->set_temp(0, Location::RequiresRegister()); | |
6426 summary->set_out(0, Location::RequiresRegister()); | |
6427 return summary; | |
6428 } | |
6429 | |
6430 | |
6431 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6432 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | |
6433 compiler->AddSlowPathCode(slow_path); | |
6434 Register value = locs()->in(0).reg(); | |
6435 Register out = locs()->out(0).reg(); | |
6436 Register temp = locs()->temp(0).reg(); | |
6437 ASSERT(value != out); | |
6438 | |
6439 Label not_smi, done; | |
6440 | |
6441 // TODO(johnmccutchan): Use range information to fast path smi / mint boxing. | |
6442 | |
6443 // Test if this value is <= kSmiMax. | |
6444 __ CompareImmediate(value, kSmiMax); | |
6445 __ b(¬_smi, HI); | |
6446 // Smi. | |
6447 __ mov(out, Operand(value)); | |
6448 __ SmiTag(out); | |
6449 __ b(&done); | |
6450 __ Bind(¬_smi); | |
6451 // Allocate a mint. | |
6452 __ TryAllocate( | |
6453 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), | |
6454 slow_path->entry_label(), | |
6455 out, | |
6456 temp); | |
6457 __ Bind(slow_path->exit_label()); | |
6458 // Copy low word into mint. | |
6459 __ StoreToOffset(kWord, | |
6460 value, | |
6461 out, | |
6462 Mint::value_offset() - kHeapObjectTag); | |
6463 // Zero high word. | |
6464 __ eor(temp, temp, Operand(temp)); | |
6465 __ StoreToOffset(kWord, | |
6466 temp, | |
6467 out, | |
6468 Mint::value_offset() - kHeapObjectTag + kWordSize); | |
6469 __ Bind(&done); | |
6470 } | |
6471 | |
6472 | |
6473 | |
6474 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, | |
6475 bool opt) const { | |
6476 const intptr_t value_cid = value()->Type()->ToCid(); | |
6477 const intptr_t kNumInputs = 1; | |
6478 const intptr_t kNumTemps = | |
6479 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; | |
6480 LocationSummary* summary = new(isolate) LocationSummary( | |
6481 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
6482 summary->set_in(0, Location::RequiresRegister()); | |
6483 if (kNumTemps > 0) { | |
6484 summary->set_temp(0, Location::RequiresRegister()); | |
6485 } | |
6486 summary->set_out(0, Location::RequiresRegister()); | |
6487 return summary; | |
6488 } | |
6489 | |
6490 | |
6491 void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6492 const intptr_t value_cid = value()->Type()->ToCid(); | |
6493 const Register value = locs()->in(0).reg(); | |
6494 const Register out = locs()->out(0).reg(); | |
6495 ASSERT(value != out); | |
6496 | |
6497 // TODO(johnmccutchan): Emit better code for constant inputs. | |
6498 if (value_cid == kMintCid) { | |
6499 __ LoadFromOffset(kWord, out, value, Mint::value_offset() - kHeapObjectTag); | |
6500 } else if (value_cid == kSmiCid) { | |
6501 __ mov(out, Operand(value)); | |
6502 __ SmiUntag(out); | |
6503 } else { | |
6504 Register temp = locs()->temp(0).reg(); | |
6505 Label* deopt = compiler->AddDeoptStub(deopt_id_, | |
6506 ICData::kDeoptUnboxInteger); | |
6507 Label is_smi, done; | |
6508 __ tst(value, Operand(kSmiTagMask)); | |
6509 __ b(&is_smi, EQ); | |
6510 __ CompareClassId(value, kMintCid, temp); | |
6511 __ b(deopt, NE); | |
6512 __ LoadFromOffset(kWord, out, value, Mint::value_offset() - kHeapObjectTag); | |
6513 __ b(&done); | |
6514 __ Bind(&is_smi); | |
6515 __ mov(out, Operand(value)); | |
6516 __ SmiUntag(out); | |
6517 __ Bind(&done); | |
6518 } | |
6519 } | |
6520 | |
6521 | |
6522 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | |
6523 bool opt) const { | |
6524 const intptr_t kNumInputs = 1; | |
6525 const intptr_t kNumTemps = 0; | |
6526 LocationSummary* summary = new(isolate) LocationSummary( | |
6527 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
6528 if (from() == kUnboxedMint) { | |
6529 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | |
6530 Location::RequiresRegister())); | |
6531 summary->set_out(0, Location::RequiresRegister()); | |
6532 } else { | |
6533 ASSERT(from() == kUnboxedUint32); | |
6534 summary->set_in(0, Location::RequiresRegister()); | |
6535 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
6536 Location::RequiresRegister())); | |
6537 } | |
6538 return summary; | |
6539 } | |
6540 | |
6541 | |
6542 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6543 if (from() == kUnboxedMint) { | |
6544 PairLocation* in_pair = locs()->in(0).AsPairLocation(); | |
6545 Register in_lo = in_pair->At(0).reg(); | |
6546 Register out = locs()->out(0).reg(); | |
6547 // Copy low word. | |
6548 __ mov(out, Operand(in_lo)); | |
6549 } else { | |
6550 ASSERT(from() == kUnboxedUint32); | |
6551 Register in = locs()->in(0).reg(); | |
6552 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
6553 Register out_lo = out_pair->At(0).reg(); | |
6554 Register out_hi = out_pair->At(1).reg(); | |
6555 // Copy low word. | |
6556 __ mov(out_lo, Operand(in)); | |
6557 // Zero upper word. | |
6558 __ eor(out_hi, out_hi, Operand(out_hi)); | |
6559 } | |
6560 } | |
6561 | |
6562 | |
6234 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6563 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
6235 bool opt) const { | 6564 bool opt) const { |
6236 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6565 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
6237 } | 6566 } |
6238 | 6567 |
6239 | 6568 |
6240 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6569 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6241 compiler->GenerateRuntimeCall(token_pos(), | 6570 compiler->GenerateRuntimeCall(token_pos(), |
6242 deopt_id(), | 6571 deopt_id(), |
6243 kThrowRuntimeEntry, | 6572 kThrowRuntimeEntry, |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6459 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 6788 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
6460 #if defined(DEBUG) | 6789 #if defined(DEBUG) |
6461 __ LoadImmediate(R4, kInvalidObjectPointer); | 6790 __ LoadImmediate(R4, kInvalidObjectPointer); |
6462 __ LoadImmediate(R5, kInvalidObjectPointer); | 6791 __ LoadImmediate(R5, kInvalidObjectPointer); |
6463 #endif | 6792 #endif |
6464 } | 6793 } |
6465 | 6794 |
6466 } // namespace dart | 6795 } // namespace dart |
6467 | 6796 |
6468 #endif // defined TARGET_ARCH_ARM | 6797 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |