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 5686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5697 if (!is_smi()) { | 5697 if (!is_smi()) { |
5698 summary->set_temp(0, Location::RequiresRegister()); | 5698 summary->set_temp(0, Location::RequiresRegister()); |
5699 } | 5699 } |
5700 summary->set_out(0, Location::RequiresRegister()); | 5700 summary->set_out(0, Location::RequiresRegister()); |
5701 return summary; | 5701 return summary; |
5702 } | 5702 } |
5703 | 5703 |
5704 | 5704 |
5705 class BoxIntegerSlowPath : public SlowPathCode { | 5705 class BoxIntegerSlowPath : public SlowPathCode { |
5706 public: | 5706 public: |
5707 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) | 5707 explicit BoxIntegerSlowPath(Definition* instruction) |
5708 : instruction_(instruction) { } | 5708 : instruction_(instruction) { } |
5709 | 5709 |
5710 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5710 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
5711 __ Comment("BoxIntegerSlowPath"); | 5711 __ Comment("BoxIntegerSlowPath"); |
5712 __ Bind(entry_label()); | 5712 __ Bind(entry_label()); |
5713 Isolate* isolate = compiler->isolate(); | 5713 Isolate* isolate = compiler->isolate(); |
5714 StubCode* stub_code = isolate->stub_code(); | 5714 StubCode* stub_code = isolate->stub_code(); |
5715 const Class& mint_class = | 5715 const Class& mint_class = |
5716 Class::ZoneHandle(isolate, isolate->object_store()->mint_class()); | 5716 Class::ZoneHandle(isolate, isolate->object_store()->mint_class()); |
5717 const Code& stub = | 5717 const Code& stub = |
5718 Code::Handle(isolate, stub_code->GetAllocationStubForClass(mint_class)); | 5718 Code::Handle(isolate, stub_code->GetAllocationStubForClass(mint_class)); |
5719 const ExternalLabel label(stub.EntryPoint()); | 5719 const ExternalLabel label(stub.EntryPoint()); |
5720 | 5720 |
5721 LocationSummary* locs = instruction_->locs(); | 5721 LocationSummary* locs = instruction_->locs(); |
5722 ASSERT(!locs->live_registers()->Contains(locs->out(0))); | 5722 ASSERT(!locs->live_registers()->Contains(locs->out(0))); |
5723 | 5723 |
5724 compiler->SaveLiveRegisters(locs); | 5724 compiler->SaveLiveRegisters(locs); |
5725 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 5725 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
5726 &label, | 5726 &label, |
5727 RawPcDescriptors::kOther, | 5727 RawPcDescriptors::kOther, |
5728 locs); | 5728 locs); |
5729 __ MoveRegister(locs->out(0).reg(), EAX); | 5729 __ MoveRegister(locs->out(0).reg(), EAX); |
5730 compiler->RestoreLiveRegisters(locs); | 5730 compiler->RestoreLiveRegisters(locs); |
5731 | 5731 |
5732 __ jmp(exit_label()); | 5732 __ jmp(exit_label()); |
5733 } | 5733 } |
5734 | 5734 |
5735 private: | 5735 private: |
5736 BoxIntegerInstr* instruction_; | 5736 Definition* instruction_; |
5737 }; | 5737 }; |
5738 | 5738 |
5739 | 5739 |
5740 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5740 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5741 if (is_smi()) { | 5741 if (is_smi()) { |
5742 PairLocation* value_pair = locs()->in(0).AsPairLocation(); | 5742 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
5743 Register value_lo = value_pair->At(0).reg(); | 5743 Register value_lo = value_pair->At(0).reg(); |
5744 Register out_reg = locs()->out(0).reg(); | 5744 Register out_reg = locs()->out(0).reg(); |
5745 __ movl(out_reg, value_lo); | 5745 __ movl(out_reg, value_lo); |
5746 __ SmiTag(out_reg); | 5746 __ SmiTag(out_reg); |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6002 | 6002 |
6003 __ notl(left_lo); | 6003 __ notl(left_lo); |
6004 __ notl(left_hi); | 6004 __ notl(left_hi); |
6005 | 6005 |
6006 if (FLAG_throw_on_javascript_int_overflow) { | 6006 if (FLAG_throw_on_javascript_int_overflow) { |
6007 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); | 6007 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); |
6008 } | 6008 } |
6009 } | 6009 } |
6010 | 6010 |
6011 | 6011 |
| 6012 CompileType BinaryUint32OpInstr::ComputeType() const { |
| 6013 return CompileType::Int(); |
| 6014 } |
| 6015 |
| 6016 |
| 6017 CompileType ShiftUint32OpInstr::ComputeType() const { |
| 6018 return CompileType::Int(); |
| 6019 } |
| 6020 |
| 6021 |
| 6022 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 6023 return CompileType::Int(); |
| 6024 } |
| 6025 |
| 6026 |
| 6027 CompileType BoxUint32Instr::ComputeType() const { |
| 6028 return CompileType::Int(); |
| 6029 } |
| 6030 |
| 6031 |
| 6032 CompileType UnboxUint32Instr::ComputeType() const { |
| 6033 return CompileType::Int(); |
| 6034 } |
| 6035 |
| 6036 |
| 6037 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 6038 bool opt) const { |
| 6039 const intptr_t kNumInputs = 2; |
| 6040 const intptr_t kNumTemps = 0; |
| 6041 LocationSummary* summary = new(isolate) LocationSummary( |
| 6042 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6043 summary->set_in(0, Location::RequiresRegister()); |
| 6044 summary->set_in(1, Location::RequiresRegister()); |
| 6045 summary->set_out(0, Location::SameAsFirstInput()); |
| 6046 return summary; |
| 6047 } |
| 6048 |
| 6049 |
| 6050 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6051 Register left = locs()->in(0).reg(); |
| 6052 Register right = locs()->in(1).reg(); |
| 6053 Register out = locs()->out(0).reg(); |
| 6054 ASSERT(out == left); |
| 6055 switch (op_kind()) { |
| 6056 case Token::kBIT_AND: |
| 6057 __ andl(out, right); |
| 6058 break; |
| 6059 case Token::kBIT_OR: |
| 6060 __ orl(out, right); |
| 6061 break; |
| 6062 case Token::kBIT_XOR: |
| 6063 __ xorl(out, right); |
| 6064 break; |
| 6065 case Token::kADD: |
| 6066 __ addl(out, right); |
| 6067 break; |
| 6068 case Token::kSUB: |
| 6069 __ subl(out, right); |
| 6070 break; |
| 6071 default: |
| 6072 UNREACHABLE(); |
| 6073 } |
| 6074 } |
| 6075 |
| 6076 |
| 6077 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 6078 bool opt) const { |
| 6079 const intptr_t kNumInputs = 2; |
| 6080 const intptr_t kNumTemps = 0; |
| 6081 LocationSummary* summary = new(isolate) LocationSummary( |
| 6082 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6083 summary->set_in(0, Location::RequiresRegister()); |
| 6084 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 6085 summary->set_out(0, Location::SameAsFirstInput()); |
| 6086 return summary; |
| 6087 } |
| 6088 |
| 6089 |
| 6090 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6091 const intptr_t kShifterLimit = 31; |
| 6092 |
| 6093 Register left = locs()->in(0).reg(); |
| 6094 Register out = locs()->out(0).reg(); |
| 6095 ASSERT(left == out); |
| 6096 |
| 6097 |
| 6098 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 6099 |
| 6100 if (locs()->in(1).IsConstant()) { |
| 6101 // Shifter is constant. |
| 6102 |
| 6103 const Object& constant = locs()->in(1).constant(); |
| 6104 ASSERT(constant.IsSmi()); |
| 6105 const intptr_t shift_value = Smi::Cast(constant).Value(); |
| 6106 |
| 6107 // Check constant shift value. |
| 6108 if (shift_value == 0) { |
| 6109 // Nothing to do. |
| 6110 } else if (shift_value < 0) { |
| 6111 // Invalid shift value. |
| 6112 __ jmp(deopt); |
| 6113 } else if (shift_value > kShifterLimit) { |
| 6114 // Result is 0. |
| 6115 __ xorl(left, left); |
| 6116 } else { |
| 6117 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
| 6118 switch (op_kind()) { |
| 6119 case Token::kSHR: |
| 6120 __ shrl(left, Immediate(shift_value)); |
| 6121 break; |
| 6122 case Token::kSHL: |
| 6123 __ shll(left, Immediate(shift_value)); |
| 6124 break; |
| 6125 default: |
| 6126 UNREACHABLE(); |
| 6127 } |
| 6128 } |
| 6129 return; |
| 6130 } |
| 6131 |
| 6132 // Non constant shift value. |
| 6133 |
| 6134 Register shifter = locs()->in(1).reg(); |
| 6135 ASSERT(shifter == ECX); |
| 6136 |
| 6137 Label done; |
| 6138 Label zero; |
| 6139 |
| 6140 // TODO(johnmccutchan): Use range information to avoid these checks. |
| 6141 __ SmiUntag(shifter); |
| 6142 __ cmpl(shifter, Immediate(0)); |
| 6143 // If shift value is < 0, deoptimize. |
| 6144 __ j(NEGATIVE, deopt); |
| 6145 __ cmpl(shifter, Immediate(kShifterLimit)); |
| 6146 // If shift value is >= 32, return zero. |
| 6147 __ j(ABOVE, &zero); |
| 6148 |
| 6149 // Do the shift. |
| 6150 switch (op_kind()) { |
| 6151 case Token::kSHR: |
| 6152 __ shrl(left, shifter); |
| 6153 __ jmp(&done); |
| 6154 break; |
| 6155 case Token::kSHL: |
| 6156 __ shll(left, shifter); |
| 6157 __ jmp(&done); |
| 6158 break; |
| 6159 default: |
| 6160 UNREACHABLE(); |
| 6161 } |
| 6162 |
| 6163 __ Bind(&zero); |
| 6164 // Shift was greater than 31 bits, just return zero. |
| 6165 __ xorl(left, left); |
| 6166 |
| 6167 // Exit path. |
| 6168 __ Bind(&done); |
| 6169 } |
| 6170 |
| 6171 |
| 6172 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 6173 bool opt) const { |
| 6174 const intptr_t kNumInputs = 1; |
| 6175 const intptr_t kNumTemps = 0; |
| 6176 LocationSummary* summary = new(isolate) LocationSummary( |
| 6177 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6178 summary->set_in(0, Location::RequiresRegister()); |
| 6179 summary->set_out(0, Location::SameAsFirstInput()); |
| 6180 return summary; |
| 6181 } |
| 6182 |
| 6183 |
| 6184 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6185 Register out = locs()->out(0).reg(); |
| 6186 ASSERT(locs()->in(0).reg() == out); |
| 6187 |
| 6188 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6189 |
| 6190 __ notl(out); |
| 6191 } |
| 6192 |
| 6193 |
| 6194 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate, |
| 6195 bool opt) const { |
| 6196 const intptr_t kNumInputs = 1; |
| 6197 const intptr_t kNumTemps = 0; |
| 6198 LocationSummary* summary = new(isolate) LocationSummary( |
| 6199 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 6200 summary->set_in(0, Location::RequiresRegister()); |
| 6201 summary->set_out(0, Location::RequiresRegister()); |
| 6202 return summary; |
| 6203 } |
| 6204 |
| 6205 |
| 6206 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6207 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
| 6208 compiler->AddSlowPathCode(slow_path); |
| 6209 Register value = locs()->in(0).reg(); |
| 6210 Register out = locs()->out(0).reg(); |
| 6211 ASSERT(value != out); |
| 6212 |
| 6213 Label not_smi, done; |
| 6214 |
| 6215 // TODO(johnmccutchan): Use range information to fast path smi / mint boxing. |
| 6216 // Test if this value is <= kSmiMax. |
| 6217 __ cmpl(value, Immediate(kSmiMax)); |
| 6218 __ j(ABOVE, ¬_smi); |
| 6219 // Smi. |
| 6220 __ movl(out, value); |
| 6221 __ SmiTag(out); |
| 6222 __ jmp(&done); |
| 6223 __ Bind(¬_smi); |
| 6224 // Allocate a mint. |
| 6225 __ TryAllocate( |
| 6226 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), |
| 6227 slow_path->entry_label(), |
| 6228 Assembler::kFarJump, |
| 6229 out, |
| 6230 kNoRegister); |
| 6231 __ Bind(slow_path->exit_label()); |
| 6232 // Copy low word into mint. |
| 6233 __ movl(FieldAddress(out, Mint::value_offset()), value); |
| 6234 // Zero high word. |
| 6235 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0)); |
| 6236 __ Bind(&done); |
| 6237 } |
| 6238 |
| 6239 |
| 6240 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, |
| 6241 bool opt) const { |
| 6242 const intptr_t value_cid = value()->Type()->ToCid(); |
| 6243 const intptr_t kNumInputs = 1; |
| 6244 const intptr_t kNumTemps = |
| 6245 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; |
| 6246 LocationSummary* summary = new(isolate) LocationSummary( |
| 6247 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6248 summary->set_in(0, Location::RequiresRegister()); |
| 6249 if (kNumTemps > 0) { |
| 6250 summary->set_temp(0, Location::RequiresRegister()); |
| 6251 } |
| 6252 summary->set_out(0, Location::SameAsFirstInput()); |
| 6253 return summary; |
| 6254 } |
| 6255 |
| 6256 |
| 6257 void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6258 const intptr_t value_cid = value()->Type()->ToCid(); |
| 6259 const Register value = locs()->in(0).reg(); |
| 6260 ASSERT(value == locs()->out(0).reg()); |
| 6261 |
| 6262 // TODO(johnmccutchan): Emit better code for constant inputs. |
| 6263 if (value_cid == kMintCid) { |
| 6264 __ movl(value, FieldAddress(value, Mint::value_offset())); |
| 6265 } else if (value_cid == kSmiCid) { |
| 6266 __ SmiUntag(value); |
| 6267 } else { |
| 6268 Register temp = locs()->temp(0).reg(); |
| 6269 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
| 6270 ICData::kDeoptUnboxInteger); |
| 6271 Label is_smi, done; |
| 6272 __ testl(value, Immediate(kSmiTagMask)); |
| 6273 __ j(ZERO, &is_smi); |
| 6274 __ CompareClassId(value, kMintCid, temp); |
| 6275 __ j(NOT_EQUAL, deopt); |
| 6276 __ movl(value, FieldAddress(value, Mint::value_offset())); |
| 6277 __ jmp(&done); |
| 6278 __ Bind(&is_smi); |
| 6279 __ SmiUntag(value); |
| 6280 __ Bind(&done); |
| 6281 } |
| 6282 } |
| 6283 |
| 6284 |
| 6285 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 6286 bool opt) const { |
| 6287 const intptr_t kNumInputs = 1; |
| 6288 const intptr_t kNumTemps = 0; |
| 6289 LocationSummary* summary = new(isolate) LocationSummary( |
| 6290 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6291 if (from() == kUnboxedMint) { |
| 6292 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6293 Location::RequiresRegister())); |
| 6294 summary->set_out(0, Location::RequiresRegister()); |
| 6295 } else { |
| 6296 ASSERT(from() == kUnboxedUint32); |
| 6297 summary->set_in(0, Location::RequiresRegister()); |
| 6298 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 6299 Location::RequiresRegister())); |
| 6300 } |
| 6301 return summary; |
| 6302 } |
| 6303 |
| 6304 |
| 6305 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6306 if (from() == kUnboxedMint) { |
| 6307 PairLocation* in_pair = locs()->in(0).AsPairLocation(); |
| 6308 Register in_lo = in_pair->At(0).reg(); |
| 6309 Register out = locs()->out(0).reg(); |
| 6310 // Copy low word. |
| 6311 __ movl(out, in_lo); |
| 6312 } else { |
| 6313 ASSERT(from() == kUnboxedUint32); |
| 6314 Register in = locs()->in(0).reg(); |
| 6315 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 6316 Register out_lo = out_pair->At(0).reg(); |
| 6317 Register out_hi = out_pair->At(1).reg(); |
| 6318 // Copy low word. |
| 6319 __ movl(out_lo, in); |
| 6320 // Zero upper word. |
| 6321 __ xorl(out_hi, out_hi); |
| 6322 } |
| 6323 } |
| 6324 |
| 6325 |
6012 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6326 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
6013 bool opt) const { | 6327 bool opt) const { |
6014 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6328 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
6015 } | 6329 } |
6016 | 6330 |
6017 | 6331 |
6018 | 6332 |
6019 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6333 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6020 compiler->GenerateRuntimeCall(token_pos(), | 6334 compiler->GenerateRuntimeCall(token_pos(), |
6021 deopt_id(), | 6335 deopt_id(), |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6363 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6677 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6364 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6678 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6365 #endif | 6679 #endif |
6366 } | 6680 } |
6367 | 6681 |
6368 } // namespace dart | 6682 } // namespace dart |
6369 | 6683 |
6370 #undef __ | 6684 #undef __ |
6371 | 6685 |
6372 #endif // defined TARGET_ARCH_IA32 | 6686 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |