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 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 302 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 302 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 303 const intptr_t kNumTemps = 1; | 303 const intptr_t kNumTemps = 1; |
| 304 LocationSummary* locs = | 304 LocationSummary* locs = |
| 305 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 305 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 306 locs->set_in(0, Location::RegisterLocation(RCX)); | 306 locs->set_in(0, Location::RegisterLocation(RCX)); |
| 307 locs->set_in(1, Location::RegisterLocation(RDX)); | 307 locs->set_in(1, Location::RegisterLocation(RDX)); |
| 308 locs->set_temp(0, Location::RegisterLocation(RBX)); | 308 locs->set_temp(0, Location::RegisterLocation(RBX)); |
| 309 locs->set_out(Location::RegisterLocation(RAX)); | 309 locs->set_out(Location::RegisterLocation(RAX)); |
| 310 return locs; | 310 return locs; |
| 311 } | 311 } |
| 312 const intptr_t kNumTemps = 0; | 312 const intptr_t kNumTemps = 1; |
| 313 LocationSummary* locs = | 313 LocationSummary* locs = |
| 314 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 314 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 315 locs->set_in(0, Location::RegisterLocation(RCX)); | 315 locs->set_in(0, Location::RegisterLocation(RCX)); |
| 316 locs->set_in(1, Location::RegisterLocation(RDX)); | 316 locs->set_in(1, Location::RegisterLocation(RDX)); |
| 317 locs->set_temp(0, Location::RegisterLocation(RBX)); | |
| 317 locs->set_out(Location::RegisterLocation(RAX)); | 318 locs->set_out(Location::RegisterLocation(RAX)); |
| 318 return locs; | 319 return locs; |
| 319 } | 320 } |
| 320 | 321 |
| 321 | 322 |
| 322 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 323 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 323 intptr_t deopt_id, | 324 intptr_t deopt_id, |
| 324 intptr_t token_pos, | 325 intptr_t token_pos, |
| 325 Token::Kind kind, | 326 Token::Kind kind, |
| 326 LocationSummary* locs) { | 327 LocationSummary* locs) { |
| 327 if (!compiler->is_optimizing()) { | 328 if (!compiler->is_optimizing()) { |
| 328 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, | 329 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
| 329 deopt_id, | 330 deopt_id, |
| 330 token_pos); | 331 token_pos); |
| 331 } | 332 } |
| 332 const String& operator_name = String::ZoneHandle(Symbols::New("==")); | 333 const String& operator_name = String::ZoneHandle(Symbols::New("==")); |
| 333 const int kNumberOfArguments = 2; | 334 const int kNumberOfArguments = 2; |
| 334 const Array& kNoArgumentNames = Array::Handle(); | 335 const Array& kNoArgumentNames = Array::Handle(); |
| 335 const int kNumArgumentsChecked = 2; | 336 const int kNumArgumentsChecked = 2; |
| 336 | 337 |
| 337 Label done, false_label, true_label; | |
| 338 Register left = locs->in(0).reg(); | |
| 339 Register right = locs->in(1).reg(); | |
| 340 __ popq(right); | |
| 341 __ popq(left); | |
| 342 const Immediate raw_null = | 338 const Immediate raw_null = |
| 343 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 339 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 344 Label check_identity, instance_call; | 340 Label check_identity; |
| 345 __ cmpq(right, raw_null); | 341 __ cmpq(Address(RSP, 0 * kWordSize), raw_null); |
| 346 __ j(EQUAL, &check_identity, Assembler::kNearJump); | 342 __ j(EQUAL, &check_identity, Assembler::kNearJump); |
| 347 __ cmpq(left, raw_null); | 343 __ cmpq(Address(RSP, 1 * kWordSize), raw_null); |
| 348 __ j(NOT_EQUAL, &instance_call, Assembler::kNearJump); | 344 __ j(EQUAL, &check_identity, Assembler::kNearJump); |
| 345 const ICData& ic_data = compiler->GenerateInstanceCall(deopt_id, | |
| 346 token_pos, | |
| 347 operator_name, | |
| 348 kNumberOfArguments, | |
| 349 kNoArgumentNames, | |
| 350 kNumArgumentsChecked, | |
| 351 locs); | |
| 352 Label check_ne; | |
| 353 __ jmp(&check_ne); | |
| 349 | 354 |
| 350 __ Bind(&check_identity); | 355 __ Bind(&check_identity); |
| 351 __ cmpq(left, right); | 356 // Call stub, load IC data in register. The stub will update ICData if |
| 352 __ j(EQUAL, &true_label); | 357 // necessary. |
| 353 if (kind == Token::kEQ) { | 358 Register ic_data_reg = locs->temp(0).reg(); |
| 354 __ LoadObject(RAX, compiler->bool_false()); | 359 ASSERT(ic_data_reg == RBX); // Stub depends on it. |
| 355 __ jmp(&done); | 360 __ LoadObject(ic_data_reg, ic_data); |
| 356 __ Bind(&true_label); | 361 compiler->GenerateCall(token_pos, |
| 357 __ LoadObject(RAX, compiler->bool_true()); | 362 &StubCode::EqualityWithNullArgLabel(), |
| 358 __ jmp(&done); | 363 PcDescriptors::kOther, |
| 359 } else { | 364 locs); |
| 360 ASSERT(kind == Token::kNE); | 365 __ Drop(2); |
| 361 __ jmp(&false_label); | 366 __ Bind(&check_ne); |
| 362 } | |
| 363 | |
| 364 __ Bind(&instance_call); | |
| 365 __ pushq(left); | |
| 366 __ pushq(right); | |
| 367 compiler->GenerateInstanceCall(deopt_id, | |
| 368 token_pos, | |
| 369 operator_name, | |
| 370 kNumberOfArguments, | |
| 371 kNoArgumentNames, | |
| 372 kNumArgumentsChecked, | |
| 373 locs); | |
| 374 if (kind == Token::kNE) { | 367 if (kind == Token::kNE) { |
| 368 Label false_label, true_label, done; | |
| 375 // Negate the condition: true label returns false and vice versa. | 369 // Negate the condition: true label returns false and vice versa. |
| 376 __ CompareObject(RAX, compiler->bool_true()); | 370 __ CompareObject(RAX, compiler->bool_true()); |
| 377 __ j(EQUAL, &true_label, Assembler::kNearJump); | 371 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 378 __ Bind(&false_label); | 372 __ Bind(&false_label); |
| 379 __ LoadObject(RAX, compiler->bool_true()); | 373 __ LoadObject(RAX, compiler->bool_true()); |
| 380 __ jmp(&done, Assembler::kNearJump); | 374 __ jmp(&done, Assembler::kNearJump); |
| 381 __ Bind(&true_label); | 375 __ Bind(&true_label); |
| 382 __ LoadObject(RAX, compiler->bool_false()); | 376 __ LoadObject(RAX, compiler->bool_false()); |
| 377 __ Bind(&done); | |
| 383 } | 378 } |
| 384 __ Bind(&done); | |
| 385 } | 379 } |
| 386 | 380 |
| 387 | 381 |
| 388 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 382 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 389 const ICData& orig_ic_data, | 383 const ICData& orig_ic_data, |
| 390 LocationSummary* locs, | 384 LocationSummary* locs, |
| 391 BranchInstr* branch, | 385 BranchInstr* branch, |
| 392 Token::Kind kind, | 386 Token::Kind kind, |
| 393 intptr_t deopt_id, | 387 intptr_t deopt_id, |
| 394 intptr_t token_pos) { | 388 intptr_t token_pos) { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 576 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 570 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 577 const LocationSummary& locs, | 571 const LocationSummary& locs, |
| 578 Token::Kind kind, | 572 Token::Kind kind, |
| 579 BranchInstr* branch) { | 573 BranchInstr* branch) { |
| 580 Location left = locs.in(0); | 574 Location left = locs.in(0); |
| 581 Location right = locs.in(1); | 575 Location right = locs.in(1); |
| 582 | 576 |
| 583 Condition true_condition = TokenKindToSmiCondition(kind); | 577 Condition true_condition = TokenKindToSmiCondition(kind); |
| 584 | 578 |
| 585 if (left.IsConstant() && right.IsConstant()) { | 579 if (left.IsConstant() && right.IsConstant()) { |
| 580 bool result = false; | |
| 581 // One of them could be NULL (for equality only). | |
| 582 if (left.constant().IsNull() || right.constant().IsNull()) { | |
| 583 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | |
| 584 result = left.constant().IsNull() && right.constant().IsNull(); | |
| 585 if (kind == Token::kNE) { | |
| 586 result = !result; | |
| 587 } | |
| 588 } else { | |
| 586 // TODO(vegorov): should be eliminated earlier by constant propagation. | 589 // TODO(vegorov): should be eliminated earlier by constant propagation. |
|
Florian Schneider
2012/10/05 09:17:35
Indentation is off.
srdjan
2012/10/09 18:06:03
Done.
| |
| 587 const bool result = FlowGraphCompiler::EvaluateCondition( | 590 result = FlowGraphCompiler::EvaluateCondition( |
| 588 true_condition, | 591 true_condition, |
| 589 Smi::Cast(left.constant()).Value(), | 592 Smi::Cast(left.constant()).Value(), |
| 590 Smi::Cast(right.constant()).Value()); | 593 Smi::Cast(right.constant()).Value()); |
| 594 } | |
| 591 | 595 |
| 592 if (branch != NULL) { | 596 if (branch != NULL) { |
| 593 branch->EmitBranchOnValue(compiler, result); | 597 branch->EmitBranchOnValue(compiler, result); |
| 594 } else { | 598 } else { |
| 595 __ LoadObject(locs.out().reg(), result ? compiler->bool_true() | 599 __ LoadObject(locs.out().reg(), result ? compiler->bool_true() |
| 596 : compiler->bool_false()); | 600 : compiler->bool_false()); |
| 597 } | 601 } |
| 598 | 602 |
| 599 return; | 603 return; |
| 600 } | 604 } |
| (...skipping 1439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2040 summary->set_temp(0, Location::RequiresRegister()); | 2044 summary->set_temp(0, Location::RequiresRegister()); |
| 2041 return summary; | 2045 return summary; |
| 2042 } | 2046 } |
| 2043 | 2047 |
| 2044 | 2048 |
| 2045 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2049 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2046 Register value = locs()->in(0).reg(); | 2050 Register value = locs()->in(0).reg(); |
| 2047 Register temp = locs()->temp(0).reg(); | 2051 Register temp = locs()->temp(0).reg(); |
| 2048 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2052 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2049 kDeoptCheckClass); | 2053 kDeoptCheckClass); |
| 2050 ASSERT(unary_checks().GetReceiverClassIdAt(0) != kSmiCid); | |
| 2051 __ testq(value, Immediate(kSmiTagMask)); | |
| 2052 __ j(ZERO, deopt); | |
| 2053 __ LoadClassId(temp, value); | |
| 2054 Label is_ok; | 2054 Label is_ok; |
| 2055 intptr_t cix = 0; | |
| 2056 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { | |
| 2057 __ testq(value, Immediate(kSmiTagMask)); | |
| 2058 __ j(ZERO, &is_ok); | |
| 2059 cix++; // Skip first check. | |
| 2060 } else { | |
| 2061 __ testq(value, Immediate(kSmiTagMask)); | |
| 2062 __ j(ZERO, deopt); | |
| 2063 } | |
| 2055 const intptr_t num_checks = unary_checks().NumberOfChecks(); | 2064 const intptr_t num_checks = unary_checks().NumberOfChecks(); |
| 2056 const bool use_near_jump = num_checks < 5; | 2065 const bool use_near_jump = num_checks < 5; |
| 2057 for (intptr_t i = 0; i < num_checks; i++) { | 2066 for (intptr_t i = cix; i < num_checks; i++) { |
| 2067 ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid); | |
| 2058 __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i))); | 2068 __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i))); |
| 2059 if (i == (num_checks - 1)) { | 2069 if (i == (num_checks - 1)) { |
| 2060 __ j(NOT_EQUAL, deopt); | 2070 __ j(NOT_EQUAL, deopt); |
| 2061 } else { | 2071 } else { |
| 2062 if (use_near_jump) { | 2072 if (use_near_jump) { |
| 2063 __ j(EQUAL, &is_ok, Assembler::kNearJump); | 2073 __ j(EQUAL, &is_ok, Assembler::kNearJump); |
| 2064 } else { | 2074 } else { |
| 2065 __ j(EQUAL, &is_ok); | 2075 __ j(EQUAL, &is_ok); |
| 2066 } | 2076 } |
| 2067 } | 2077 } |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2185 void UnboxedMintUnaryOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2195 void UnboxedMintUnaryOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2186 UNIMPLEMENTED(); | 2196 UNIMPLEMENTED(); |
| 2187 } | 2197 } |
| 2188 | 2198 |
| 2189 | 2199 |
| 2190 } // namespace dart | 2200 } // namespace dart |
| 2191 | 2201 |
| 2192 #undef __ | 2202 #undef __ |
| 2193 | 2203 |
| 2194 #endif // defined TARGET_ARCH_X64 | 2204 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |