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 __ SmiUntag(shifter); | |
6141 __ cmpl(shifter, Immediate(0)); | |
6142 // If shift value is < 0, deoptimize. | |
6143 __ j(NEGATIVE, deopt); | |
6144 __ cmpl(shifter, Immediate(kShifterLimit)); | |
6145 // If shift value is >= 32, return zero. | |
6146 __ j(ABOVE, &zero); | |
Florian Schneider
2014/07/10 13:05:05
Use range information to eliminate these checkes i
Cutch
2014/07/10 17:12:53
TODO added.
| |
6147 | |
6148 // Do the shift. | |
6149 switch (op_kind()) { | |
6150 case Token::kSHR: | |
6151 __ shrl(left, shifter); | |
6152 __ jmp(&done); | |
6153 break; | |
6154 case Token::kSHL: | |
6155 __ shll(left, shifter); | |
6156 __ jmp(&done); | |
6157 break; | |
6158 default: | |
6159 UNREACHABLE(); | |
6160 } | |
6161 | |
6162 __ Bind(&zero); | |
6163 // Shift was greater than 31 bits, just return zero. | |
6164 __ xorl(left, left); | |
6165 | |
6166 // Exit path. | |
6167 __ Bind(&done); | |
6168 } | |
6169 | |
6170 | |
6171 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, | |
6172 bool opt) const { | |
6173 const intptr_t kNumInputs = 1; | |
6174 const intptr_t kNumTemps = 0; | |
6175 LocationSummary* summary = new(isolate) LocationSummary( | |
6176 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
6177 summary->set_in(0, Location::RequiresRegister()); | |
6178 summary->set_out(0, Location::SameAsFirstInput()); | |
6179 return summary; | |
6180 } | |
6181 | |
6182 | |
6183 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6184 Register out = locs()->out(0).reg(); | |
6185 ASSERT(locs()->in(0).reg() == out); | |
6186 | |
6187 ASSERT(op_kind() == Token::kBIT_NOT); | |
6188 | |
6189 __ notl(out); | |
6190 } | |
6191 | |
6192 | |
6193 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate, | |
6194 bool opt) const { | |
6195 const intptr_t kNumInputs = 1; | |
6196 const intptr_t kNumTemps = 0; | |
6197 LocationSummary* summary = new(isolate) LocationSummary( | |
6198 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | |
6199 summary->set_in(0, Location::RequiresRegister()); | |
6200 summary->set_out(0, Location::RequiresRegister()); | |
6201 return summary; | |
6202 } | |
6203 | |
6204 | |
6205 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6206 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | |
6207 compiler->AddSlowPathCode(slow_path); | |
6208 Register value = locs()->in(0).reg(); | |
6209 Register out = locs()->out(0).reg(); | |
6210 ASSERT(value != out); | |
6211 | |
6212 Label not_smi, done; | |
6213 | |
6214 // TODO(johnmccutchan): Use range information to fast path smi / mint boxing. | |
6215 // Test if this value is <= kSmiMax. | |
6216 __ cmpl(value, Immediate(kSmiMax)); | |
6217 __ j(ABOVE, ¬_smi); | |
6218 // Smi. | |
6219 __ movl(out, value); | |
6220 __ SmiTag(out); | |
6221 __ jmp(&done); | |
6222 __ Bind(¬_smi); | |
6223 // Allocate a mint. | |
6224 __ TryAllocate( | |
6225 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), | |
6226 slow_path->entry_label(), | |
6227 Assembler::kFarJump, | |
6228 out, | |
6229 kNoRegister); | |
6230 __ Bind(slow_path->exit_label()); | |
6231 // Copy low word into mint. | |
6232 __ movl(FieldAddress(out, Mint::value_offset()), value); | |
6233 // Zero high word. | |
6234 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0)); | |
6235 __ Bind(&done); | |
6236 } | |
6237 | |
6238 | |
6239 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, | |
6240 bool opt) const { | |
6241 const intptr_t value_cid = value()->Type()->ToCid(); | |
6242 const intptr_t kNumInputs = 1; | |
6243 const intptr_t kNumTemps = | |
6244 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; | |
6245 LocationSummary* summary = new(isolate) LocationSummary( | |
6246 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
6247 summary->set_in(0, Location::RequiresRegister()); | |
6248 if (kNumTemps > 0) { | |
6249 summary->set_temp(0, Location::RequiresRegister()); | |
6250 } | |
6251 summary->set_out(0, Location::SameAsFirstInput()); | |
6252 return summary; | |
6253 } | |
6254 | |
6255 | |
6256 void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6257 const intptr_t value_cid = value()->Type()->ToCid(); | |
6258 const Register value = locs()->in(0).reg(); | |
6259 ASSERT(value == locs()->out(0).reg()); | |
6260 | |
6261 // TODO(johnmccutchan): Emit better code for constant inputs. | |
6262 if (value_cid == kMintCid) { | |
6263 __ movl(value, FieldAddress(value, Mint::value_offset())); | |
6264 } else if (value_cid == kSmiCid) { | |
6265 __ SmiUntag(value); | |
6266 } else { | |
6267 Register temp = locs()->temp(0).reg(); | |
6268 Label* deopt = compiler->AddDeoptStub(deopt_id_, | |
6269 ICData::kDeoptUnboxInteger); | |
6270 Label is_smi, done; | |
6271 __ testl(value, Immediate(kSmiTagMask)); | |
6272 __ j(ZERO, &is_smi); | |
6273 __ CompareClassId(value, kMintCid, temp); | |
6274 __ j(NOT_EQUAL, deopt); | |
6275 __ movl(value, FieldAddress(value, Mint::value_offset())); | |
6276 __ jmp(&done); | |
6277 __ Bind(&is_smi); | |
6278 __ SmiUntag(value); | |
6279 __ Bind(&done); | |
6280 } | |
6281 } | |
6282 | |
6283 | |
6284 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | |
6285 bool opt) const { | |
6286 const intptr_t kNumInputs = 1; | |
6287 const intptr_t kNumTemps = 0; | |
6288 LocationSummary* summary = new(isolate) LocationSummary( | |
6289 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
6290 if (from() == kUnboxedMint) { | |
6291 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | |
6292 Location::RequiresRegister())); | |
6293 summary->set_out(0, Location::RequiresRegister()); | |
6294 } else { | |
6295 ASSERT(from() == kUnboxedUint32); | |
6296 summary->set_in(0, Location::RequiresRegister()); | |
6297 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
6298 Location::RequiresRegister())); | |
6299 } | |
6300 return summary; | |
6301 } | |
6302 | |
6303 | |
6304 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6305 if (from() == kUnboxedMint) { | |
6306 PairLocation* in_pair = locs()->in(0).AsPairLocation(); | |
6307 Register in_lo = in_pair->At(0).reg(); | |
6308 Register out = locs()->out(0).reg(); | |
6309 // Copy low word. | |
6310 __ movl(out, in_lo); | |
6311 } else { | |
6312 ASSERT(from() == kUnboxedUint32); | |
6313 Register in = locs()->in(0).reg(); | |
6314 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
6315 Register out_lo = out_pair->At(0).reg(); | |
6316 Register out_hi = out_pair->At(1).reg(); | |
6317 // Copy low word. | |
6318 __ movl(out_lo, in); | |
6319 // Zero upper word. | |
6320 __ xorl(out_hi, out_hi); | |
6321 } | |
6322 } | |
6323 | |
6324 | |
6012 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6325 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
6013 bool opt) const { | 6326 bool opt) const { |
6014 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6327 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
6015 } | 6328 } |
6016 | 6329 |
6017 | 6330 |
6018 | 6331 |
6019 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6332 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6020 compiler->GenerateRuntimeCall(token_pos(), | 6333 compiler->GenerateRuntimeCall(token_pos(), |
6021 deopt_id(), | 6334 deopt_id(), |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6363 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6676 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6364 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 6677 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6365 #endif | 6678 #endif |
6366 } | 6679 } |
6367 | 6680 |
6368 } // namespace dart | 6681 } // namespace dart |
6369 | 6682 |
6370 #undef __ | 6683 #undef __ |
6371 | 6684 |
6372 #endif // defined TARGET_ARCH_IA32 | 6685 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |