| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 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 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 kConditionTypeErrorRuntimeEntry); | 191 kConditionTypeErrorRuntimeEntry); |
| 192 // We should never return here. | 192 // We should never return here. |
| 193 __ int3(); | 193 __ int3(); |
| 194 | 194 |
| 195 __ Bind(&done); | 195 __ Bind(&done); |
| 196 ASSERT(obj == result); | 196 ASSERT(obj == result); |
| 197 } | 197 } |
| 198 | 198 |
| 199 | 199 |
| 200 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 200 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
| 201 LocationSummary* locs = new LocationSummary(2, 0); | 201 const intptr_t kNumInputs = 2; |
| 202 locs->set_in(0, Location::RequiresRegister()); | 202 if (operands_class_id() == kSmi) { |
| 203 locs->set_in(1, Location::RequiresRegister()); | 203 const intptr_t kNumTemps = 1; |
| 204 if (!is_fused_with_branch()) { | 204 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 205 locs->set_out(Location::RegisterLocation(RAX)); | 205 locs->set_in(0, Location::RequiresRegister()); |
| 206 locs->set_in(1, Location::RequiresRegister()); |
| 207 locs->set_temp(0, Location::RequiresRegister()); |
| 208 if (!is_fused_with_branch()) { |
| 209 locs->set_out(Location::RequiresRegister()); |
| 210 } |
| 211 return locs; |
| 206 } | 212 } |
| 207 return locs; | 213 if (operands_class_id() == kObject) { |
| 214 const intptr_t kNumTemps = 0; |
| 215 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 216 locs->set_in(0, Location::RequiresRegister()); |
| 217 locs->set_in(1, Location::RequiresRegister()); |
| 218 if (!is_fused_with_branch()) { |
| 219 locs->set_out(Location::RegisterLocation(RAX)); |
| 220 } |
| 221 return locs; |
| 222 } |
| 223 UNREACHABLE(); |
| 224 return NULL; |
| 208 } | 225 } |
| 209 | 226 |
| 210 | 227 |
| 211 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 228 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
| 212 Register left = locs()->in(0).reg(); | 229 EqualityCompareComp* comp) { |
| 213 Register right = locs()->in(1).reg(); | 230 // TODO(srdjan): Should we always include NULL test (common case)? |
| 231 Register left = comp->locs()->in(0).reg(); |
| 232 Register right = comp->locs()->in(1).reg(); |
| 233 Register result = comp->locs()->out().reg(); |
| 234 Register temp = comp->locs()->temp(0).reg(); |
| 235 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 236 comp->token_index(), |
| 237 comp->try_index(), |
| 238 kDeoptSmiCompareSmis, |
| 239 left, |
| 240 right); |
| 241 __ movq(temp, left); |
| 242 __ orq(temp, right); |
| 243 __ testq(temp, Immediate(kSmiTagMask)); |
| 244 __ j(NOT_ZERO, deopt); |
| 245 __ cmpq(left, right); |
| 246 if (comp->is_fused_with_branch()) { |
| 247 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 248 } else { |
| 249 Label load_true, done; |
| 250 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 251 __ LoadObject(result, compiler->bool_false()); |
| 252 __ jmp(&done, Assembler::kNearJump); |
| 253 __ Bind(&load_true); |
| 254 __ LoadObject(result, compiler->bool_true()); |
| 255 __ Bind(&done); |
| 256 } |
| 257 } |
| 214 | 258 |
| 259 |
| 260 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 261 EqualityCompareComp* comp) { |
| 215 const Immediate raw_null = | 262 const Immediate raw_null = |
| 216 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 263 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 264 Register left = comp->locs()->in(0).reg(); |
| 265 Register right = comp->locs()->in(1).reg(); |
| 217 Label done, non_null_compare; | 266 Label done, non_null_compare; |
| 218 | |
| 219 __ cmpq(left, raw_null); | 267 __ cmpq(left, raw_null); |
| 220 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 268 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
| 221 // Comparison with NULL is "===". | 269 // Comparison with NULL is "===". |
| 222 __ cmpq(left, right); | 270 __ cmpq(left, right); |
| 223 if (!is_fused_with_branch()) { | 271 if (comp->is_fused_with_branch()) { |
| 224 Register result = locs()->out().reg(); | 272 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 273 } else { |
| 274 Register result = comp->locs()->out().reg(); |
| 225 Label load_true; | 275 Label load_true; |
| 226 __ j(EQUAL, &load_true, Assembler::kNearJump); | 276 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 227 __ LoadObject(result, compiler->bool_false()); | 277 __ LoadObject(result, compiler->bool_false()); |
| 228 __ jmp(&done, Assembler::kNearJump); | 278 __ jmp(&done, Assembler::kNearJump); |
| 229 __ Bind(&load_true); | 279 __ Bind(&load_true); |
| 230 __ LoadObject(result, compiler->bool_true()); | 280 __ LoadObject(result, compiler->bool_true()); |
| 231 } else { | |
| 232 fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | |
| 233 } | 281 } |
| 234 __ jmp(&done); | 282 __ jmp(&done); |
| 235 | 283 |
| 236 | |
| 237 __ Bind(&non_null_compare); | 284 __ Bind(&non_null_compare); |
| 238 __ pushq(left); | 285 __ pushq(left); |
| 239 __ pushq(right); | 286 __ pushq(right); |
| 240 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 287 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); |
| 241 const int kNumberOfArguments = 2; | 288 const int kNumberOfArguments = 2; |
| 242 const Array& kNoArgumentNames = Array::Handle(); | 289 const Array& kNoArgumentNames = Array::Handle(); |
| 243 const int kNumArgumentsChecked = 1; | 290 const int kNumArgumentsChecked = 1; |
| 244 | 291 |
| 245 compiler->GenerateInstanceCall(cid(), | 292 compiler->GenerateInstanceCall(comp->cid(), |
| 246 token_index(), | 293 comp->token_index(), |
| 247 try_index(), | 294 comp->try_index(), |
| 248 operator_name, | 295 operator_name, |
| 249 kNumberOfArguments, | 296 kNumberOfArguments, |
| 250 kNoArgumentNames, | 297 kNoArgumentNames, |
| 251 kNumArgumentsChecked); | 298 kNumArgumentsChecked); |
| 252 ASSERT(fused_with_branch() != NULL || locs()->out().reg() == RAX); | 299 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == RAX)); |
| 253 | 300 |
| 254 if (fused_with_branch() != NULL) { | 301 if (comp->is_fused_with_branch()) { |
| 255 __ CompareObject(RAX, compiler->bool_true()); | 302 __ CompareObject(RAX, compiler->bool_true()); |
| 256 fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 303 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 257 } | 304 } |
| 305 __ Bind(&done); |
| 306 } |
| 258 | 307 |
| 259 __ Bind(&done); | 308 |
| 309 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 310 if (operands_class_id() == kSmi) { |
| 311 EmitSmiEqualityCompare(compiler, this); |
| 312 return; |
| 313 } |
| 314 if (operands_class_id() == kObject) { |
| 315 EmitGenericEqualityCompare(compiler, this); |
| 316 return; |
| 317 } |
| 318 UNREACHABLE(); |
| 260 } | 319 } |
| 261 | 320 |
| 262 | 321 |
| 263 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 322 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| 264 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { | 323 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { |
| 265 const intptr_t kNumInputs = 2; | 324 const intptr_t kNumInputs = 2; |
| 266 const intptr_t kNumTemps = 1; | 325 const intptr_t kNumTemps = 1; |
| 267 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 326 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
| 268 summary->set_in(0, Location::RequiresRegister()); | 327 summary->set_in(0, Location::RequiresRegister()); |
| 269 summary->set_in(1, Location::RequiresRegister()); | 328 summary->set_in(1, Location::RequiresRegister()); |
| (...skipping 1265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 __ cvtsi2sd(XMM0, value); | 1594 __ cvtsi2sd(XMM0, value); |
| 1536 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1595 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1537 } | 1596 } |
| 1538 | 1597 |
| 1539 | 1598 |
| 1540 } // namespace dart | 1599 } // namespace dart |
| 1541 | 1600 |
| 1542 #undef __ | 1601 #undef __ |
| 1543 | 1602 |
| 1544 #endif // defined TARGET_ARCH_X64 | 1603 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |