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 5735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5746 if (!is_smi()) { | 5746 if (!is_smi()) { |
5747 summary->set_temp(0, Location::RequiresRegister()); | 5747 summary->set_temp(0, Location::RequiresRegister()); |
5748 } | 5748 } |
5749 summary->set_out(0, Location::RequiresRegister()); | 5749 summary->set_out(0, Location::RequiresRegister()); |
5750 return summary; | 5750 return summary; |
5751 } | 5751 } |
5752 | 5752 |
5753 | 5753 |
5754 class BoxIntegerSlowPath : public SlowPathCode { | 5754 class BoxIntegerSlowPath : public SlowPathCode { |
5755 public: | 5755 public: |
5756 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) | 5756 explicit BoxIntegerSlowPath(Definition* instruction) |
5757 : instruction_(instruction) { } | 5757 : instruction_(instruction) { } |
5758 | 5758 |
5759 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5759 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
5760 __ Comment("BoxIntegerSlowPath"); | 5760 __ Comment("BoxIntegerSlowPath"); |
5761 __ Bind(entry_label()); | 5761 __ Bind(entry_label()); |
5762 Isolate* isolate = compiler->isolate(); | 5762 Isolate* isolate = compiler->isolate(); |
5763 StubCode* stub_code = isolate->stub_code(); | 5763 StubCode* stub_code = isolate->stub_code(); |
5764 const Class& mint_class = | 5764 const Class& mint_class = |
5765 Class::ZoneHandle(isolate, isolate->object_store()->mint_class()); | 5765 Class::ZoneHandle(isolate, isolate->object_store()->mint_class()); |
5766 const Code& stub = | 5766 const Code& stub = |
5767 Code::Handle(isolate, stub_code->GetAllocationStubForClass(mint_class)); | 5767 Code::Handle(isolate, stub_code->GetAllocationStubForClass(mint_class)); |
5768 const ExternalLabel label(stub.EntryPoint()); | 5768 const ExternalLabel label(stub.EntryPoint()); |
5769 | 5769 |
5770 LocationSummary* locs = instruction_->locs(); | 5770 LocationSummary* locs = instruction_->locs(); |
5771 ASSERT(!locs->live_registers()->Contains(locs->out(0))); | 5771 ASSERT(!locs->live_registers()->Contains(locs->out(0))); |
5772 | 5772 |
5773 compiler->SaveLiveRegisters(locs); | 5773 compiler->SaveLiveRegisters(locs); |
5774 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 5774 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
5775 &label, | 5775 &label, |
5776 RawPcDescriptors::kOther, | 5776 RawPcDescriptors::kOther, |
5777 locs); | 5777 locs); |
5778 __ MoveRegister(locs->out(0).reg(), EAX); | 5778 __ MoveRegister(locs->out(0).reg(), EAX); |
5779 compiler->RestoreLiveRegisters(locs); | 5779 compiler->RestoreLiveRegisters(locs); |
5780 | 5780 |
5781 __ jmp(exit_label()); | 5781 __ jmp(exit_label()); |
5782 } | 5782 } |
5783 | 5783 |
5784 private: | 5784 private: |
5785 BoxIntegerInstr* instruction_; | 5785 Definition* instruction_; |
5786 }; | 5786 }; |
5787 | 5787 |
5788 | 5788 |
5789 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5789 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5790 if (is_smi()) { | 5790 if (is_smi()) { |
5791 PairLocation* value_pair = locs()->in(0).AsPairLocation(); | 5791 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
5792 Register value_lo = value_pair->At(0).reg(); | 5792 Register value_lo = value_pair->At(0).reg(); |
5793 Register out_reg = locs()->out(0).reg(); | 5793 Register out_reg = locs()->out(0).reg(); |
5794 __ movl(out_reg, value_lo); | 5794 __ movl(out_reg, value_lo); |
5795 __ SmiTag(out_reg); | 5795 __ SmiTag(out_reg); |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6158 | 6158 |
6159 __ notl(left_lo); | 6159 __ notl(left_lo); |
6160 __ notl(left_hi); | 6160 __ notl(left_hi); |
6161 | 6161 |
6162 if (FLAG_throw_on_javascript_int_overflow) { | 6162 if (FLAG_throw_on_javascript_int_overflow) { |
6163 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); | 6163 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); |
6164 } | 6164 } |
6165 } | 6165 } |
6166 | 6166 |
6167 | 6167 |
| 6168 CompileType BinaryUint32OpInstr::ComputeType() const { |
| 6169 return CompileType::Int(); |
| 6170 } |
| 6171 |
| 6172 |
| 6173 CompileType ShiftUint32OpInstr::ComputeType() const { |
| 6174 return CompileType::Int(); |
| 6175 } |
| 6176 |
| 6177 |
| 6178 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 6179 return CompileType::Int(); |
| 6180 } |
| 6181 |
| 6182 |
| 6183 CompileType BoxUint32Instr::ComputeType() const { |
| 6184 return CompileType::Int(); |
| 6185 } |
| 6186 |
| 6187 |
| 6188 CompileType UnboxUint32Instr::ComputeType() const { |
| 6189 return CompileType::Int(); |
| 6190 } |
| 6191 |
| 6192 |
| 6193 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 6194 bool opt) const { |
| 6195 const intptr_t kNumInputs = 2; |
| 6196 const intptr_t kNumTemps = 0; |
| 6197 LocationSummary* summary = new(isolate) LocationSummary( |
| 6198 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6199 summary->set_in(0, Location::RequiresRegister()); |
| 6200 summary->set_in(1, Location::RequiresRegister()); |
| 6201 summary->set_out(0, Location::SameAsFirstInput()); |
| 6202 return summary; |
| 6203 } |
| 6204 |
| 6205 |
| 6206 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6207 Register left = locs()->in(0).reg(); |
| 6208 Register right = locs()->in(1).reg(); |
| 6209 Register out = locs()->out(0).reg(); |
| 6210 ASSERT(out == left); |
| 6211 switch (op_kind()) { |
| 6212 case Token::kBIT_AND: |
| 6213 __ andl(out, right); |
| 6214 break; |
| 6215 case Token::kBIT_OR: |
| 6216 __ orl(out, right); |
| 6217 break; |
| 6218 case Token::kBIT_XOR: |
| 6219 __ xorl(out, right); |
| 6220 break; |
| 6221 case Token::kADD: |
| 6222 __ addl(out, right); |
| 6223 break; |
| 6224 case Token::kSUB: |
| 6225 __ subl(out, right); |
| 6226 break; |
| 6227 default: |
| 6228 UNREACHABLE(); |
| 6229 } |
| 6230 } |
| 6231 |
| 6232 |
| 6233 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 6234 bool opt) const { |
| 6235 const intptr_t kNumInputs = 2; |
| 6236 const intptr_t kNumTemps = 0; |
| 6237 LocationSummary* summary = new(isolate) LocationSummary( |
| 6238 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6239 summary->set_in(0, Location::RequiresRegister()); |
| 6240 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 6241 summary->set_out(0, Location::SameAsFirstInput()); |
| 6242 return summary; |
| 6243 } |
| 6244 |
| 6245 |
| 6246 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6247 const intptr_t kShifterLimit = 31; |
| 6248 |
| 6249 Register left = locs()->in(0).reg(); |
| 6250 Register out = locs()->out(0).reg(); |
| 6251 ASSERT(left == out); |
| 6252 |
| 6253 |
| 6254 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 6255 |
| 6256 if (locs()->in(1).IsConstant()) { |
| 6257 // Shifter is constant. |
| 6258 |
| 6259 const Object& constant = locs()->in(1).constant(); |
| 6260 ASSERT(constant.IsSmi()); |
| 6261 const intptr_t shift_value = Smi::Cast(constant).Value(); |
| 6262 |
| 6263 // Check constant shift value. |
| 6264 if (shift_value == 0) { |
| 6265 // Nothing to do. |
| 6266 } else if (shift_value < 0) { |
| 6267 // Invalid shift value. |
| 6268 __ jmp(deopt); |
| 6269 } else if (shift_value > kShifterLimit) { |
| 6270 // Result is 0. |
| 6271 __ xorl(left, left); |
| 6272 } else { |
| 6273 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
| 6274 switch (op_kind()) { |
| 6275 case Token::kSHR: |
| 6276 __ shrl(left, Immediate(shift_value)); |
| 6277 break; |
| 6278 case Token::kSHL: |
| 6279 __ shll(left, Immediate(shift_value)); |
| 6280 break; |
| 6281 default: |
| 6282 UNREACHABLE(); |
| 6283 } |
| 6284 } |
| 6285 return; |
| 6286 } |
| 6287 |
| 6288 // Non constant shift value. |
| 6289 |
| 6290 Register shifter = locs()->in(1).reg(); |
| 6291 ASSERT(shifter == ECX); |
| 6292 |
| 6293 Label done; |
| 6294 Label zero; |
| 6295 |
| 6296 // TODO(johnmccutchan): Use range information to avoid these checks. |
| 6297 __ SmiUntag(shifter); |
| 6298 __ cmpl(shifter, Immediate(0)); |
| 6299 // If shift value is < 0, deoptimize. |
| 6300 __ j(NEGATIVE, deopt); |
| 6301 __ cmpl(shifter, Immediate(kShifterLimit)); |
| 6302 // If shift value is >= 32, return zero. |
| 6303 __ j(ABOVE, &zero); |
| 6304 |
| 6305 // Do the shift. |
| 6306 switch (op_kind()) { |
| 6307 case Token::kSHR: |
| 6308 __ shrl(left, shifter); |
| 6309 __ jmp(&done); |
| 6310 break; |
| 6311 case Token::kSHL: |
| 6312 __ shll(left, shifter); |
| 6313 __ jmp(&done); |
| 6314 break; |
| 6315 default: |
| 6316 UNREACHABLE(); |
| 6317 } |
| 6318 |
| 6319 __ Bind(&zero); |
| 6320 // Shift was greater than 31 bits, just return zero. |
| 6321 __ xorl(left, left); |
| 6322 |
| 6323 // Exit path. |
| 6324 __ Bind(&done); |
| 6325 } |
| 6326 |
| 6327 |
| 6328 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 6329 bool opt) const { |
| 6330 const intptr_t kNumInputs = 1; |
| 6331 const intptr_t kNumTemps = 0; |
| 6332 LocationSummary* summary = new(isolate) LocationSummary( |
| 6333 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6334 summary->set_in(0, Location::RequiresRegister()); |
| 6335 summary->set_out(0, Location::SameAsFirstInput()); |
| 6336 return summary; |
| 6337 } |
| 6338 |
| 6339 |
| 6340 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6341 Register out = locs()->out(0).reg(); |
| 6342 ASSERT(locs()->in(0).reg() == out); |
| 6343 |
| 6344 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6345 |
| 6346 __ notl(out); |
| 6347 } |
| 6348 |
| 6349 |
| 6350 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate, |
| 6351 bool opt) const { |
| 6352 const intptr_t kNumInputs = 1; |
| 6353 const intptr_t kNumTemps = 0; |
| 6354 LocationSummary* summary = new(isolate) LocationSummary( |
| 6355 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 6356 summary->set_in(0, Location::RequiresRegister()); |
| 6357 summary->set_out(0, Location::RequiresRegister()); |
| 6358 return summary; |
| 6359 } |
| 6360 |
| 6361 |
| 6362 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6363 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
| 6364 compiler->AddSlowPathCode(slow_path); |
| 6365 Register value = locs()->in(0).reg(); |
| 6366 Register out = locs()->out(0).reg(); |
| 6367 ASSERT(value != out); |
| 6368 |
| 6369 Label not_smi, done; |
| 6370 |
| 6371 // TODO(johnmccutchan): Use range information to fast path smi / mint boxing. |
| 6372 // Test if this value is <= kSmiMax. |
| 6373 __ cmpl(value, Immediate(kSmiMax)); |
| 6374 __ j(ABOVE, ¬_smi); |
| 6375 // Smi. |
| 6376 __ movl(out, value); |
| 6377 __ SmiTag(out); |
| 6378 __ jmp(&done); |
| 6379 __ Bind(¬_smi); |
| 6380 // Allocate a mint. |
| 6381 __ TryAllocate( |
| 6382 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), |
| 6383 slow_path->entry_label(), |
| 6384 Assembler::kFarJump, |
| 6385 out, |
| 6386 kNoRegister); |
| 6387 __ Bind(slow_path->exit_label()); |
| 6388 // Copy low word into mint. |
| 6389 __ movl(FieldAddress(out, Mint::value_offset()), value); |
| 6390 // Zero high word. |
| 6391 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0)); |
| 6392 __ Bind(&done); |
| 6393 } |
| 6394 |
| 6395 |
| 6396 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, |
| 6397 bool opt) const { |
| 6398 const intptr_t value_cid = value()->Type()->ToCid(); |
| 6399 const intptr_t kNumInputs = 1; |
| 6400 const intptr_t kNumTemps = |
| 6401 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; |
| 6402 LocationSummary* summary = new(isolate) LocationSummary( |
| 6403 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6404 summary->set_in(0, Location::RequiresRegister()); |
| 6405 if (kNumTemps > 0) { |
| 6406 summary->set_temp(0, Location::RequiresRegister()); |
| 6407 } |
| 6408 summary->set_out(0, Location::SameAsFirstInput()); |
| 6409 return summary; |
| 6410 } |
| 6411 |
| 6412 |
| 6413 void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6414 const intptr_t value_cid = value()->Type()->ToCid(); |
| 6415 const Register value = locs()->in(0).reg(); |
| 6416 ASSERT(value == locs()->out(0).reg()); |
| 6417 |
| 6418 // TODO(johnmccutchan): Emit better code for constant inputs. |
| 6419 if (value_cid == kMintCid) { |
| 6420 __ movl(value, FieldAddress(value, Mint::value_offset())); |
| 6421 } else if (value_cid == kSmiCid) { |
| 6422 __ SmiUntag(value); |
| 6423 } else { |
| 6424 Register temp = locs()->temp(0).reg(); |
| 6425 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
| 6426 ICData::kDeoptUnboxInteger); |
| 6427 Label is_smi, done; |
| 6428 __ testl(value, Immediate(kSmiTagMask)); |
| 6429 __ j(ZERO, &is_smi); |
| 6430 __ CompareClassId(value, kMintCid, temp); |
| 6431 __ j(NOT_EQUAL, deopt); |
| 6432 __ movl(value, FieldAddress(value, Mint::value_offset())); |
| 6433 __ jmp(&done); |
| 6434 __ Bind(&is_smi); |
| 6435 __ SmiUntag(value); |
| 6436 __ Bind(&done); |
| 6437 } |
| 6438 } |
| 6439 |
| 6440 |
| 6441 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 6442 bool opt) const { |
| 6443 const intptr_t kNumInputs = 1; |
| 6444 const intptr_t kNumTemps = 0; |
| 6445 LocationSummary* summary = new(isolate) LocationSummary( |
| 6446 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6447 if (from() == kUnboxedMint) { |
| 6448 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6449 Location::RequiresRegister())); |
| 6450 summary->set_out(0, Location::RequiresRegister()); |
| 6451 } else { |
| 6452 ASSERT(from() == kUnboxedUint32); |
| 6453 summary->set_in(0, Location::RequiresRegister()); |
| 6454 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 6455 Location::RequiresRegister())); |
| 6456 } |
| 6457 return summary; |
| 6458 } |
| 6459 |
| 6460 |
| 6461 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6462 if (from() == kUnboxedMint) { |
| 6463 PairLocation* in_pair = locs()->in(0).AsPairLocation(); |
| 6464 Register in_lo = in_pair->At(0).reg(); |
| 6465 Register out = locs()->out(0).reg(); |
| 6466 // Copy low word. |
| 6467 __ movl(out, in_lo); |
| 6468 } else { |
| 6469 ASSERT(from() == kUnboxedUint32); |
| 6470 Register in = locs()->in(0).reg(); |
| 6471 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 6472 Register out_lo = out_pair->At(0).reg(); |
| 6473 Register out_hi = out_pair->At(1).reg(); |
| 6474 // Copy low word. |
| 6475 __ movl(out_lo, in); |
| 6476 // Zero upper word. |
| 6477 __ xorl(out_hi, out_hi); |
| 6478 } |
| 6479 } |
| 6480 |
| 6481 |
6168 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6482 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
6169 bool opt) const { | 6483 bool opt) const { |
6170 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6484 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
6171 } | 6485 } |
6172 | 6486 |
6173 | 6487 |
6174 | 6488 |
6175 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6489 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6176 compiler->GenerateRuntimeCall(token_pos(), | 6490 compiler->GenerateRuntimeCall(token_pos(), |
6177 deopt_id(), | 6491 deopt_id(), |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6519 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6833 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6520 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6834 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6521 #endif | 6835 #endif |
6522 } | 6836 } |
6523 | 6837 |
6524 } // namespace dart | 6838 } // namespace dart |
6525 | 6839 |
6526 #undef __ | 6840 #undef __ |
6527 | 6841 |
6528 #endif // defined TARGET_ARCH_IA32 | 6842 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |