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