| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 kConditionTypeErrorRuntimeEntry); | 182 kConditionTypeErrorRuntimeEntry); |
| 183 // We should never return here. | 183 // We should never return here. |
| 184 __ int3(); | 184 __ int3(); |
| 185 | 185 |
| 186 __ Bind(&done); | 186 __ Bind(&done); |
| 187 ASSERT(obj == result); | 187 ASSERT(obj == result); |
| 188 } | 188 } |
| 189 | 189 |
| 190 | 190 |
| 191 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 191 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
| 192 LocationSummary* locs = new LocationSummary(2, 0); | 192 const intptr_t kNumInputs = 2; |
| 193 locs->set_in(0, Location::RequiresRegister()); | 193 if (operands_class_id() == kSmi) { |
| 194 locs->set_in(1, Location::RequiresRegister()); | 194 const intptr_t kNumTemps = 1; |
| 195 if (!is_fused_with_branch()) { | 195 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 196 locs->set_out(Location::RegisterLocation(EAX)); | 196 locs->set_in(0, Location::RequiresRegister()); |
| 197 locs->set_in(1, Location::RequiresRegister()); |
| 198 locs->set_temp(0, Location::RequiresRegister()); |
| 199 if (!is_fused_with_branch()) { |
| 200 locs->set_out(Location::RequiresRegister()); |
| 201 } |
| 202 return locs; |
| 197 } | 203 } |
| 198 return locs; | 204 if (operands_class_id() == kObject) { |
| 205 const intptr_t kNumTemps = 0; |
| 206 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 207 locs->set_in(0, Location::RequiresRegister()); |
| 208 locs->set_in(1, Location::RequiresRegister()); |
| 209 if (!is_fused_with_branch()) { |
| 210 locs->set_out(Location::RegisterLocation(EAX)); |
| 211 } |
| 212 return locs; |
| 213 } |
| 214 UNREACHABLE(); |
| 215 return NULL; |
| 199 } | 216 } |
| 200 | 217 |
| 201 | 218 |
| 202 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 219 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
| 203 Register left = locs()->in(0).reg(); | 220 EqualityCompareComp* comp) { |
| 204 Register right = locs()->in(1).reg(); | 221 Register left = comp->locs()->in(0).reg(); |
| 222 Register right = comp->locs()->in(1).reg(); |
| 223 // TODO(srdjan): Should we always include NULL test (common case)? |
| 224 Register result = comp->locs()->out().reg(); |
| 225 Register temp = comp->locs()->temp(0).reg(); |
| 226 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 227 comp->token_index(), |
| 228 comp->try_index(), |
| 229 kDeoptSmiCompareSmis, |
| 230 left, |
| 231 right); |
| 232 __ movl(temp, left); |
| 233 __ orl(temp, right); |
| 234 __ testl(temp, Immediate(kSmiTagMask)); |
| 235 __ j(NOT_ZERO, deopt); |
| 236 __ cmpl(left, right); |
| 237 if (comp->is_fused_with_branch()) { |
| 238 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 239 } else { |
| 240 Label load_true, done; |
| 241 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 242 __ LoadObject(result, compiler->bool_false()); |
| 243 __ jmp(&done, Assembler::kNearJump); |
| 244 __ Bind(&load_true); |
| 245 __ LoadObject(result, compiler->bool_true()); |
| 246 __ Bind(&done); |
| 247 } |
| 248 } |
| 205 | 249 |
| 250 |
| 251 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 252 EqualityCompareComp* comp) { |
| 253 Register left = comp->locs()->in(0).reg(); |
| 254 Register right = comp->locs()->in(1).reg(); |
| 206 const Immediate raw_null = | 255 const Immediate raw_null = |
| 207 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 256 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 208 Label done, non_null_compare; | 257 Label done, non_null_compare; |
| 209 __ cmpl(left, raw_null); | 258 __ cmpl(left, raw_null); |
| 210 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 259 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
| 211 // Comparison with NULL is "===". | 260 // Comparison with NULL is "===". |
| 212 __ cmpl(left, right); | 261 __ cmpl(left, right); |
| 213 if (!is_fused_with_branch()) { | 262 if (comp->is_fused_with_branch()) { |
| 214 Register result = locs()->out().reg(); | 263 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 264 } else { |
| 265 Register result = comp->locs()->out().reg(); |
| 215 Label load_true; | 266 Label load_true; |
| 216 __ j(EQUAL, &load_true, Assembler::kNearJump); | 267 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 217 __ LoadObject(result, compiler->bool_false()); | 268 __ LoadObject(result, compiler->bool_false()); |
| 218 __ jmp(&done, Assembler::kNearJump); | 269 __ jmp(&done, Assembler::kNearJump); |
| 219 __ Bind(&load_true); | 270 __ Bind(&load_true); |
| 220 __ LoadObject(result, compiler->bool_true()); | 271 __ LoadObject(result, compiler->bool_true()); |
| 221 } else { | |
| 222 fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | |
| 223 } | 272 } |
| 224 __ jmp(&done); | 273 __ jmp(&done); |
| 225 | 274 |
| 226 __ Bind(&non_null_compare); | 275 __ Bind(&non_null_compare); |
| 227 __ pushl(left); | 276 __ pushl(left); |
| 228 __ pushl(right); | 277 __ pushl(right); |
| 229 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 278 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); |
| 230 const int kNumberOfArguments = 2; | 279 const int kNumberOfArguments = 2; |
| 231 const Array& kNoArgumentNames = Array::Handle(); | 280 const Array& kNoArgumentNames = Array::Handle(); |
| 232 const int kNumArgumentsChecked = 1; | 281 const int kNumArgumentsChecked = 1; |
| 233 | 282 |
| 234 compiler->GenerateInstanceCall(cid(), | 283 compiler->GenerateInstanceCall(comp->cid(), |
| 235 token_index(), | 284 comp->token_index(), |
| 236 try_index(), | 285 comp->try_index(), |
| 237 operator_name, | 286 operator_name, |
| 238 kNumberOfArguments, | 287 kNumberOfArguments, |
| 239 kNoArgumentNames, | 288 kNoArgumentNames, |
| 240 kNumArgumentsChecked); | 289 kNumArgumentsChecked); |
| 241 ASSERT(fused_with_branch() != NULL || locs()->out().reg() == EAX); | 290 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == EAX)); |
| 242 | 291 |
| 243 if (fused_with_branch() != NULL) { | 292 if (comp->is_fused_with_branch()) { |
| 244 __ CompareObject(EAX, compiler->bool_true()); | 293 __ CompareObject(EAX, compiler->bool_true()); |
| 245 fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 294 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 246 } | 295 } |
| 296 __ Bind(&done); |
| 297 } |
| 247 | 298 |
| 248 __ Bind(&done); | 299 |
| 300 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 301 if (operands_class_id() == kSmi) { |
| 302 EmitSmiEqualityCompare(compiler, this); |
| 303 return; |
| 304 } |
| 305 if (operands_class_id() == kObject) { |
| 306 EmitGenericEqualityCompare(compiler, this); |
| 307 return; |
| 308 } |
| 309 UNREACHABLE(); |
| 249 } | 310 } |
| 250 | 311 |
| 251 | 312 |
| 252 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 313 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| 253 if ((operands_class_id() == kSmi) || (operands_class_id() == kDouble)) { | 314 if ((operands_class_id() == kSmi) || (operands_class_id() == kDouble)) { |
| 254 const intptr_t kNumInputs = 2; | 315 const intptr_t kNumInputs = 2; |
| 255 const intptr_t kNumTemps = 1; | 316 const intptr_t kNumTemps = 1; |
| 256 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 317 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
| 257 summary->set_in(0, Location::RequiresRegister()); | 318 summary->set_in(0, Location::RequiresRegister()); |
| 258 summary->set_in(1, Location::RequiresRegister()); | 319 summary->set_in(1, Location::RequiresRegister()); |
| (...skipping 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1518 __ cvtsi2sd(XMM0, value); | 1579 __ cvtsi2sd(XMM0, value); |
| 1519 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1580 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1520 } | 1581 } |
| 1521 | 1582 |
| 1522 | 1583 |
| 1523 } // namespace dart | 1584 } // namespace dart |
| 1524 | 1585 |
| 1525 #undef __ | 1586 #undef __ |
| 1526 | 1587 |
| 1527 #endif // defined TARGET_ARCH_X64 | 1588 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |