Chromium Code Reviews| 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(); | |
|
zra
2014/07/11 22:42:47
const Register here and below
| |
| 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 22:42:46
rm comment
| |
| 6334 __ mov(out, Operand(left)); | |
| 6335 } else if (shift_value < 0) { | |
| 6336 // Invalid shift value. | |
| 6337 __ b(deopt); | |
| 6338 } else if (shift_value > kShifterLimit) { | |
| 6339 // Result is 0. | |
| 6340 __ eor(out, out, Operand(out)); | |
| 6341 } else { | |
| 6342 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | |
| 6343 switch (op_kind()) { | |
| 6344 case Token::kSHR: | |
| 6345 __ Lsr(out, left, shift_value); | |
| 6346 break; | |
| 6347 case Token::kSHL: | |
| 6348 __ Lsl(out, left, shift_value); | |
| 6349 break; | |
| 6350 default: | |
| 6351 UNREACHABLE(); | |
| 6352 } | |
| 6353 } | |
| 6354 return; | |
| 6355 } | |
| 6356 | |
| 6357 // Non constant shift value. | |
| 6358 | |
| 6359 Register shifter = locs()->in(1).reg(); | |
| 6360 | |
| 6361 __ mov(temp, Operand(shifter)); | |
| 6362 __ SmiUntag(temp); | |
| 6363 __ CompareImmediate(temp, 0); | |
| 6364 // If shift value is < 0, deoptimize. | |
| 6365 __ b(deopt, LT); | |
| 6366 __ CompareImmediate(temp, kShifterLimit); | |
| 6367 // > kShifterLimit, result is 0. | |
| 6368 __ eor(out, out, Operand(out), HI); | |
| 6369 // Do the shift. | |
| 6370 switch (op_kind()) { | |
| 6371 case Token::kSHR: | |
| 6372 __ Lsr(out, left, temp, LS); | |
| 6373 break; | |
| 6374 case Token::kSHL: | |
| 6375 __ Lsl(out, left, temp, LS); | |
| 6376 break; | |
| 6377 default: | |
| 6378 UNREACHABLE(); | |
| 6379 } | |
| 6380 } | |
| 6381 | |
| 6382 | |
| 6383 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, | |
| 6384 bool opt) const { | |
| 6385 const intptr_t kNumInputs = 1; | |
| 6386 const intptr_t kNumTemps = 0; | |
| 6387 LocationSummary* summary = new(isolate) LocationSummary( | |
| 6388 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 6389 summary->set_in(0, Location::RequiresRegister()); | |
| 6390 summary->set_out(0, Location::RequiresRegister()); | |
| 6391 return summary; | |
| 6392 } | |
| 6393 | |
| 6394 | |
| 6395 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 6396 Register left = locs()->in(0).reg(); | |
| 6397 Register out = locs()->out(0).reg(); | |
| 6398 ASSERT(left != out); | |
| 6399 | |
| 6400 ASSERT(op_kind() == Token::kBIT_NOT); | |
| 6401 | |
| 6402 __ mvn(out, Operand(left)); | |
| 6403 } | |
| 6404 | |
| 6405 | |
| 6406 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate, | |
| 6407 bool opt) const { | |
| 6408 const intptr_t kNumInputs = 1; | |
| 6409 const intptr_t kNumTemps = 1; | |
| 6410 LocationSummary* summary = new(isolate) LocationSummary( | |
| 6411 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | |
| 6412 summary->set_in(0, Location::RequiresRegister()); | |
| 6413 summary->set_temp(0, Location::RequiresRegister()); | |
| 6414 summary->set_out(0, Location::RequiresRegister()); | |
| 6415 return summary; | |
| 6416 } | |
| 6417 | |
| 6418 | |
| 6419 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 6420 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | |
| 6421 compiler->AddSlowPathCode(slow_path); | |
| 6422 Register value = locs()->in(0).reg(); | |
| 6423 Register out = locs()->out(0).reg(); | |
| 6424 Register temp = locs()->temp(0).reg(); | |
| 6425 ASSERT(value != out); | |
| 6426 | |
| 6427 Label not_smi, done; | |
| 6428 | |
| 6429 // TODO(johnmccutchan): Use range information to fast path smi / mint boxing. | |
| 6430 | |
| 6431 // Test if this value is <= kSmiMax. | |
| 6432 __ CompareImmediate(value, kSmiMax); | |
| 6433 __ b(¬_smi, HI); | |
| 6434 // Smi. | |
| 6435 __ mov(out, Operand(value)); | |
| 6436 __ SmiTag(out); | |
| 6437 __ b(&done); | |
| 6438 __ Bind(¬_smi); | |
| 6439 // Allocate a mint. | |
| 6440 __ TryAllocate( | |
| 6441 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), | |
| 6442 slow_path->entry_label(), | |
| 6443 out, | |
| 6444 temp); | |
| 6445 __ Bind(slow_path->exit_label()); | |
| 6446 // Copy low word into mint. | |
| 6447 __ StoreToOffset(kWord, | |
| 6448 value, | |
| 6449 out, | |
| 6450 Mint::value_offset() - kHeapObjectTag); | |
| 6451 // Zero high word. | |
| 6452 __ eor(temp, temp, Operand(temp)); | |
| 6453 __ StoreToOffset(kWord, | |
| 6454 temp, | |
| 6455 out, | |
| 6456 Mint::value_offset() - kHeapObjectTag + kWordSize); | |
| 6457 __ Bind(&done); | |
| 6458 } | |
| 6459 | |
| 6460 | |
| 6461 | |
| 6462 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, | |
| 6463 bool opt) const { | |
| 6464 const intptr_t value_cid = value()->Type()->ToCid(); | |
| 6465 const intptr_t kNumInputs = 1; | |
| 6466 const intptr_t kNumTemps = | |
| 6467 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; | |
| 6468 LocationSummary* summary = new(isolate) LocationSummary( | |
| 6469 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 6470 summary->set_in(0, Location::RequiresRegister()); | |
| 6471 if (kNumTemps > 0) { | |
| 6472 summary->set_temp(0, Location::RequiresRegister()); | |
| 6473 } | |
| 6474 summary->set_out(0, Location::RequiresRegister()); | |
| 6475 return summary; | |
| 6476 } | |
| 6477 | |
| 6478 | |
| 6479 void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 6480 const intptr_t value_cid = value()->Type()->ToCid(); | |
| 6481 const Register value = locs()->in(0).reg(); | |
| 6482 const Register out = locs()->out(0).reg(); | |
| 6483 ASSERT(value != out); | |
| 6484 | |
| 6485 // TODO(johnmccutchan): Emit better code for constant inputs. | |
| 6486 if (value_cid == kMintCid) { | |
| 6487 __ LoadFromOffset(kWord, out, value, Mint::value_offset() - kHeapObjectTag); | |
| 6488 } else if (value_cid == kSmiCid) { | |
| 6489 __ mov(out, Operand(value)); | |
| 6490 __ SmiUntag(out); | |
| 6491 } else { | |
| 6492 Register temp = locs()->temp(0).reg(); | |
| 6493 Label* deopt = compiler->AddDeoptStub(deopt_id_, | |
| 6494 ICData::kDeoptUnboxInteger); | |
| 6495 Label is_smi, done; | |
| 6496 __ tst(value, Operand(kSmiTagMask)); | |
|
zra
2014/07/11 22:42:47
Sorry I missed this one before. You can eliminate
Cutch
2014/07/14 14:57:33
Done.
| |
| 6497 __ b(&is_smi, EQ); | |
| 6498 __ CompareClassId(value, kMintCid, temp); | |
| 6499 __ b(deopt, NE); | |
| 6500 __ LoadFromOffset(kWord, out, value, Mint::value_offset() - kHeapObjectTag); | |
| 6501 __ b(&done); | |
| 6502 __ Bind(&is_smi); | |
| 6503 __ mov(out, Operand(value)); | |
| 6504 __ SmiUntag(out); | |
| 6505 __ Bind(&done); | |
| 6506 } | |
| 6507 } | |
| 6508 | |
| 6509 | |
| 6510 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | |
| 6511 bool opt) const { | |
| 6512 const intptr_t kNumInputs = 1; | |
| 6513 const intptr_t kNumTemps = 0; | |
| 6514 LocationSummary* summary = new(isolate) LocationSummary( | |
| 6515 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 6516 if (from() == kUnboxedMint) { | |
| 6517 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | |
| 6518 Location::RequiresRegister())); | |
| 6519 summary->set_out(0, Location::RequiresRegister()); | |
| 6520 } else { | |
| 6521 ASSERT(from() == kUnboxedUint32); | |
| 6522 summary->set_in(0, Location::RequiresRegister()); | |
| 6523 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
| 6524 Location::RequiresRegister())); | |
| 6525 } | |
| 6526 return summary; | |
| 6527 } | |
| 6528 | |
| 6529 | |
| 6530 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 6531 if (from() == kUnboxedMint) { | |
| 6532 PairLocation* in_pair = locs()->in(0).AsPairLocation(); | |
| 6533 Register in_lo = in_pair->At(0).reg(); | |
| 6534 Register out = locs()->out(0).reg(); | |
| 6535 // Copy low word. | |
| 6536 __ mov(out, Operand(in_lo)); | |
| 6537 } else { | |
| 6538 ASSERT(from() == kUnboxedUint32); | |
| 6539 Register in = locs()->in(0).reg(); | |
| 6540 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
| 6541 Register out_lo = out_pair->At(0).reg(); | |
| 6542 Register out_hi = out_pair->At(1).reg(); | |
| 6543 // Copy low word. | |
| 6544 __ mov(out_lo, Operand(in)); | |
| 6545 // Zero upper word. | |
| 6546 __ eor(out_hi, out_hi, Operand(out_hi)); | |
| 6547 } | |
| 6548 } | |
| 6549 | |
| 6550 | |
| 6234 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6551 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
| 6235 bool opt) const { | 6552 bool opt) const { |
| 6236 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6553 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
| 6237 } | 6554 } |
| 6238 | 6555 |
| 6239 | 6556 |
| 6240 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6557 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6241 compiler->GenerateRuntimeCall(token_pos(), | 6558 compiler->GenerateRuntimeCall(token_pos(), |
| 6242 deopt_id(), | 6559 deopt_id(), |
| 6243 kThrowRuntimeEntry, | 6560 kThrowRuntimeEntry, |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6459 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 6776 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
| 6460 #if defined(DEBUG) | 6777 #if defined(DEBUG) |
| 6461 __ LoadImmediate(R4, kInvalidObjectPointer); | 6778 __ LoadImmediate(R4, kInvalidObjectPointer); |
| 6462 __ LoadImmediate(R5, kInvalidObjectPointer); | 6779 __ LoadImmediate(R5, kInvalidObjectPointer); |
| 6463 #endif | 6780 #endif |
| 6464 } | 6781 } |
| 6465 | 6782 |
| 6466 } // namespace dart | 6783 } // namespace dart |
| 6467 | 6784 |
| 6468 #endif // defined TARGET_ARCH_ARM | 6785 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |