Chromium Code Reviews| 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 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 const intptr_t kNumInputs = 2; | 201 const intptr_t kNumInputs = 2; |
| 202 if (operands_class_id() == kSmi) { | 202 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { |
| 203 const intptr_t kNumTemps = 1; | 203 const intptr_t kNumTemps = 1; |
| 204 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 204 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 205 locs->set_in(0, Location::RequiresRegister()); | 205 locs->set_in(0, Location::RequiresRegister()); |
| 206 locs->set_in(1, Location::RequiresRegister()); | 206 locs->set_in(1, Location::RequiresRegister()); |
| 207 locs->set_temp(0, Location::RequiresRegister()); | 207 locs->set_temp(0, Location::RequiresRegister()); |
| 208 if (!is_fused_with_branch()) { | 208 if (!is_fused_with_branch()) { |
| 209 locs->set_out(Location::RequiresRegister()); | 209 locs->set_out(Location::RequiresRegister()); |
| 210 } | 210 } |
| 211 return locs; | 211 return locs; |
| 212 } | 212 } |
| 213 if (operands_class_id() == kObject) { | 213 if (NumTargets() > 0) { |
| 214 const intptr_t kNumTemps = 0; | 214 const intptr_t kNumTemps = 1; |
| 215 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 215 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 216 locs->set_in(0, Location::RequiresRegister()); | 216 locs->set_in(0, Location::RequiresRegister()); |
| 217 locs->set_in(1, Location::RequiresRegister()); | 217 locs->set_in(1, Location::RequiresRegister()); |
| 218 locs->set_temp(0, Location::RequiresRegister()); | |
| 218 if (!is_fused_with_branch()) { | 219 if (!is_fused_with_branch()) { |
| 219 locs->set_out(Location::RegisterLocation(RAX)); | 220 locs->set_out(Location::RegisterLocation(RAX)); |
| 220 } | 221 } |
| 221 return locs; | 222 return locs; |
| 222 } | 223 } |
| 223 UNREACHABLE(); | 224 const intptr_t kNumTemps = 0; |
| 224 return NULL; | 225 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 226 locs->set_in(0, Location::RequiresRegister()); | |
| 227 locs->set_in(1, Location::RequiresRegister()); | |
| 228 if (!is_fused_with_branch()) { | |
| 229 locs->set_out(Location::RegisterLocation(RAX)); | |
| 230 } | |
| 231 return locs; | |
| 225 } | 232 } |
| 226 | 233 |
| 227 | 234 |
| 228 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 235 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
| 229 EqualityCompareComp* comp) { | 236 EqualityCompareComp* comp) { |
| 230 Register left = comp->locs()->in(0).reg(); | 237 Register left = comp->locs()->in(0).reg(); |
| 231 Register right = comp->locs()->in(1).reg(); | 238 Register right = comp->locs()->in(1).reg(); |
| 232 Register temp = comp->locs()->temp(0).reg(); | 239 Register temp = comp->locs()->temp(0).reg(); |
| 233 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 240 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 234 comp->token_index(), | 241 comp->token_index(), |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 250 __ j(EQUAL, &load_true, Assembler::kNearJump); | 257 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 251 __ LoadObject(result, compiler->bool_false()); | 258 __ LoadObject(result, compiler->bool_false()); |
| 252 __ jmp(&done, Assembler::kNearJump); | 259 __ jmp(&done, Assembler::kNearJump); |
| 253 __ Bind(&load_true); | 260 __ Bind(&load_true); |
| 254 __ LoadObject(result, compiler->bool_true()); | 261 __ LoadObject(result, compiler->bool_true()); |
| 255 __ Bind(&done); | 262 __ Bind(&done); |
| 256 } | 263 } |
| 257 } | 264 } |
| 258 | 265 |
| 259 | 266 |
| 267 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | |
| 268 EqualityCompareComp* comp) { | |
| 269 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | |
| 270 comp->cid(), | |
| 271 comp->token_index(), | |
| 272 comp->try_index()); | |
| 273 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | |
| 274 const int kNumberOfArguments = 2; | |
| 275 const Array& kNoArgumentNames = Array::Handle(); | |
| 276 const int kNumArgumentsChecked = 2; | |
| 277 | |
| 278 compiler->GenerateInstanceCall(comp->cid(), | |
| 279 comp->token_index(), | |
| 280 comp->try_index(), | |
| 281 operator_name, | |
| 282 kNumberOfArguments, | |
| 283 kNoArgumentNames, | |
| 284 kNumArgumentsChecked); | |
| 285 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == RAX)); | |
| 286 | |
| 287 if (comp->is_fused_with_branch()) { | |
| 288 __ CompareObject(RAX, compiler->bool_true()); | |
| 289 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | |
| 290 } | |
| 291 } | |
| 292 | |
| 293 | |
| 294 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | |
| 295 EqualityCompareComp* comp, | |
| 296 Register left, | |
| 297 Register right) { | |
| 298 ASSERT(comp->NumTargets() > 0); | |
| 299 Label* deopt = compiler->AddDeoptStub(comp->cid(), | |
| 300 comp->token_index(), | |
| 301 comp->try_index(), | |
| 302 kDeoptEquality); | |
| 303 __ testq(left, Immediate(kSmiTagMask)); | |
| 304 Register temp = comp->locs()->temp(0).reg(); | |
| 305 if (comp->ClassIdAt(0) == kSmi) { | |
| 306 Label done, load_class_id; | |
| 307 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | |
| 308 __ movq(temp, Immediate(kSmi)); | |
| 309 __ jmp(&done, Assembler::kNearJump); | |
| 310 __ Bind(&load_class_id); | |
| 311 __ LoadClassId(temp, left); | |
| 312 __ Bind(&done); | |
| 313 } else { | |
| 314 __ j(ZERO, deopt); // Smi deopts. | |
| 315 __ LoadClassId(temp, left); | |
| 316 } | |
| 317 Label done; | |
| 318 for (intptr_t i = 0; i < comp->NumTargets(); i++) { | |
| 319 ASSERT(comp->ClassIdAt(i) != kSmi || i == 0); | |
|
regis
2012/06/14 23:59:41
ditto
srdjan
2012/06/15 00:27:19
Done.
| |
| 320 Label next_test; | |
| 321 __ cmpq(temp, Immediate(comp->ClassIdAt(i))); | |
| 322 __ j(NOT_EQUAL, &next_test, Assembler::kNearJump); | |
| 323 const Function& target = *comp->TargetAt(i); | |
| 324 ObjectStore* object_store = Isolate::Current()->object_store(); | |
| 325 if (target.owner() == object_store->object_class()) { | |
| 326 // Object.== is same as ===. | |
| 327 __ Drop(2); | |
| 328 __ cmpq(left, right); | |
| 329 if (comp->is_fused_with_branch()) { | |
| 330 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | |
| 331 } else { | |
| 332 // This case should be rare. | |
| 333 Register result = comp->locs()->out().reg(); | |
| 334 Label load_true; | |
| 335 __ j(EQUAL, &load_true, Assembler::kNearJump); | |
| 336 __ LoadObject(result, compiler->bool_false()); | |
| 337 __ jmp(&done); | |
| 338 __ Bind(&load_true); | |
| 339 __ LoadObject(result, compiler->bool_true()); | |
| 340 } | |
| 341 } else { | |
| 342 const int kNumberOfArguments = 2; | |
| 343 const Array& kNoArgumentNames = Array::Handle(); | |
| 344 compiler->GenerateStaticCall(comp->cid(), | |
| 345 comp->token_index(), | |
| 346 comp->try_index(), | |
| 347 target, | |
| 348 kNumberOfArguments, | |
| 349 kNoArgumentNames); | |
| 350 ASSERT(comp->is_fused_with_branch() || | |
| 351 (comp->locs()->out().reg() == RAX)); | |
| 352 if (comp->is_fused_with_branch()) { | |
| 353 __ CompareObject(RAX, compiler->bool_true()); | |
| 354 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | |
| 355 } | |
| 356 } | |
| 357 __ jmp(&done); | |
| 358 __ Bind(&next_test); | |
| 359 } | |
| 360 // Fall through leads to deoptimization | |
| 361 __ jmp(deopt); | |
| 362 __ Bind(&done); | |
| 363 } | |
| 364 | |
| 365 | |
| 366 | |
| 367 // First test if receiver is NULL, in which case === is applied. | |
| 368 // If type feedback was provided (lists of <class-id, target>), do a | |
| 369 // type by type check (either === or static call to the operator. | |
| 260 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 370 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 261 EqualityCompareComp* comp) { | 371 EqualityCompareComp* comp) { |
| 262 const Immediate raw_null = | 372 const Immediate raw_null = |
| 263 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 373 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 264 Register left = comp->locs()->in(0).reg(); | 374 Register left = comp->locs()->in(0).reg(); |
| 265 Register right = comp->locs()->in(1).reg(); | 375 Register right = comp->locs()->in(1).reg(); |
| 266 Label done, non_null_compare; | 376 Label done, non_null_compare; |
| 267 __ cmpq(left, raw_null); | 377 __ cmpq(left, raw_null); |
| 268 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 378 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
| 269 // Comparison with NULL is "===". | 379 // Comparison with NULL is "===". |
| 270 __ cmpq(left, right); | 380 __ cmpq(left, right); |
| 271 if (comp->is_fused_with_branch()) { | 381 if (comp->is_fused_with_branch()) { |
| 272 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 382 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 273 } else { | 383 } else { |
| 274 Register result = comp->locs()->out().reg(); | 384 Register result = comp->locs()->out().reg(); |
| 275 Label load_true; | 385 Label load_true; |
| 276 __ j(EQUAL, &load_true, Assembler::kNearJump); | 386 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 277 __ LoadObject(result, compiler->bool_false()); | 387 __ LoadObject(result, compiler->bool_false()); |
| 278 __ jmp(&done, Assembler::kNearJump); | 388 __ jmp(&done); |
| 279 __ Bind(&load_true); | 389 __ Bind(&load_true); |
| 280 __ LoadObject(result, compiler->bool_true()); | 390 __ LoadObject(result, compiler->bool_true()); |
| 281 } | 391 } |
| 282 __ jmp(&done); | 392 __ jmp(&done); |
| 283 | 393 |
| 284 __ Bind(&non_null_compare); | 394 __ Bind(&non_null_compare); // Receiver is not null. |
| 285 __ pushq(left); | 395 __ pushq(left); |
| 286 __ pushq(right); | 396 __ pushq(right); |
| 287 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 397 if (comp->NumTargets() > 0) { |
| 288 comp->cid(), | 398 EmitEqualityAsPolymorphicCall(compiler, comp, left, right); |
| 289 comp->token_index(), | 399 } else { |
| 290 comp->try_index()); | 400 EmitEqualityAsInstanceCall(compiler, comp); |
| 291 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | |
| 292 const int kNumberOfArguments = 2; | |
| 293 const Array& kNoArgumentNames = Array::Handle(); | |
| 294 const int kNumArgumentsChecked = 2; | |
| 295 | |
| 296 compiler->GenerateInstanceCall(comp->cid(), | |
| 297 comp->token_index(), | |
| 298 comp->try_index(), | |
| 299 operator_name, | |
| 300 kNumberOfArguments, | |
| 301 kNoArgumentNames, | |
| 302 kNumArgumentsChecked); | |
| 303 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == RAX)); | |
| 304 | |
| 305 if (comp->is_fused_with_branch()) { | |
| 306 __ CompareObject(RAX, compiler->bool_true()); | |
| 307 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | |
| 308 } | 401 } |
| 309 __ Bind(&done); | 402 __ Bind(&done); |
| 310 } | 403 } |
| 311 | 404 |
| 312 | 405 |
| 313 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 406 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 314 if (operands_class_id() == kSmi) { | 407 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { |
| 315 EmitSmiEqualityCompare(compiler, this); | 408 EmitSmiEqualityCompare(compiler, this); |
| 316 return; | 409 return; |
| 317 } | 410 } |
| 318 if (operands_class_id() == kObject) { | 411 EmitGenericEqualityCompare(compiler, this); |
| 319 EmitGenericEqualityCompare(compiler, this); | |
| 320 return; | |
| 321 } | |
| 322 UNREACHABLE(); | |
| 323 } | 412 } |
| 324 | 413 |
| 325 | 414 |
| 326 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 415 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| 327 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { | 416 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { |
| 328 const intptr_t kNumInputs = 2; | 417 const intptr_t kNumInputs = 2; |
| 329 const intptr_t kNumTemps = 1; | 418 const intptr_t kNumTemps = 1; |
| 330 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 419 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
| 331 summary->set_in(0, Location::RequiresRegister()); | 420 summary->set_in(0, Location::RequiresRegister()); |
| 332 summary->set_in(1, Location::RequiresRegister()); | 421 summary->set_in(1, Location::RequiresRegister()); |
| (...skipping 1313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1646 instance_call()->argument_names()); | 1735 instance_call()->argument_names()); |
| 1647 } | 1736 } |
| 1648 __ Bind(&done); | 1737 __ Bind(&done); |
| 1649 } | 1738 } |
| 1650 | 1739 |
| 1651 } // namespace dart | 1740 } // namespace dart |
| 1652 | 1741 |
| 1653 #undef __ | 1742 #undef __ |
| 1654 | 1743 |
| 1655 #endif // defined TARGET_ARCH_X64 | 1744 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |