| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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_DBC. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_DBC. |
| 6 #if defined(TARGET_ARCH_DBC) | 6 #if defined(TARGET_ARCH_DBC) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 M(BinaryUint32Op) \ | 96 M(BinaryUint32Op) \ |
| 97 M(ShiftUint32Op) \ | 97 M(ShiftUint32Op) \ |
| 98 M(UnaryUint32Op) \ | 98 M(UnaryUint32Op) \ |
| 99 M(UnboxedIntConverter) \ | 99 M(UnboxedIntConverter) \ |
| 100 M(GrowRegExpStack) \ | 100 M(GrowRegExpStack) \ |
| 101 M(BoxInteger32) \ | 101 M(BoxInteger32) \ |
| 102 M(UnboxInteger32) \ | 102 M(UnboxInteger32) \ |
| 103 M(CheckedSmiOp) \ | 103 M(CheckedSmiOp) \ |
| 104 M(CheckArrayBound) \ | 104 M(CheckArrayBound) \ |
| 105 M(CheckClass) \ | 105 M(CheckClass) \ |
| 106 M(TestSmi) \ | |
| 107 M(RelationalOp) \ | 106 M(RelationalOp) \ |
| 108 M(EqualityCompare) \ | 107 M(EqualityCompare) \ |
| 109 M(LoadIndexed) | 108 M(LoadIndexed) |
| 110 | 109 |
| 111 // Location summaries actually are not used by the unoptimizing DBC compiler | 110 // Location summaries actually are not used by the unoptimizing DBC compiler |
| 112 // because we don't allocate any registers. | 111 // because we don't allocate any registers. |
| 113 static LocationSummary* CreateLocationSummary( | 112 static LocationSummary* CreateLocationSummary( |
| 114 Zone* zone, | 113 Zone* zone, |
| 115 intptr_t num_inputs, | 114 intptr_t num_inputs, |
| 116 Location output = Location::NoLocation(), | 115 Location output = Location::NoLocation(), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 UNIMPLEMENTED(); \ | 151 UNIMPLEMENTED(); \ |
| 153 } | 152 } |
| 154 | 153 |
| 155 #define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name) \ | 154 #define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name) \ |
| 156 void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) { \ | 155 void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) { \ |
| 157 UNIMPLEMENTED(); \ | 156 UNIMPLEMENTED(); \ |
| 158 } \ | 157 } \ |
| 159 Condition Name##Instr::EmitComparisonCode(FlowGraphCompiler*, \ | 158 Condition Name##Instr::EmitComparisonCode(FlowGraphCompiler*, \ |
| 160 BranchLabels) { \ | 159 BranchLabels) { \ |
| 161 UNIMPLEMENTED(); \ | 160 UNIMPLEMENTED(); \ |
| 162 return EQ; \ | 161 return NEXT_IS_TRUE; \ |
| 163 } | 162 } |
| 164 | 163 |
| 165 #define DEFINE_UNIMPLEMENTED(Name) \ | 164 #define DEFINE_UNIMPLEMENTED(Name) \ |
| 166 DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name) \ | 165 DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name) \ |
| 167 DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) \ | 166 DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) \ |
| 168 | 167 |
| 169 FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED) | 168 FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED) |
| 170 | 169 |
| 171 #undef DEFINE_UNIMPLEMENTED | 170 #undef DEFINE_UNIMPLEMENTED |
| 172 | 171 |
| 173 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestCids) | 172 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestCids) |
| 174 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestSmi) | |
| 175 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(RelationalOp) | 173 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(RelationalOp) |
| 176 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare) | 174 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare) |
| 177 | 175 |
| 178 | 176 |
| 179 EMIT_NATIVE_CODE(InstanceOf, 2, Location::SameAsFirstInput(), | 177 EMIT_NATIVE_CODE(InstanceOf, 2, Location::SameAsFirstInput(), |
| 180 LocationSummary::kCall) { | 178 LocationSummary::kCall) { |
| 181 SubtypeTestCache& test_cache = SubtypeTestCache::Handle(); | 179 SubtypeTestCache& test_cache = SubtypeTestCache::Handle(); |
| 182 if (!type().IsVoidType() && type().IsInstantiated()) { | 180 if (!type().IsVoidType() && type().IsInstantiated()) { |
| 183 test_cache = SubtypeTestCache::New(); | 181 test_cache = SubtypeTestCache::New(); |
| 184 } | 182 } |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 | 374 |
| 377 if (compiler->is_optimizing()) { | 375 if (compiler->is_optimizing()) { |
| 378 __ PopLocal(locs()->out(0).reg()); | 376 __ PopLocal(locs()->out(0).reg()); |
| 379 } | 377 } |
| 380 } | 378 } |
| 381 | 379 |
| 382 | 380 |
| 383 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 381 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 384 Condition true_condition, | 382 Condition true_condition, |
| 385 BranchLabels labels) { | 383 BranchLabels labels) { |
| 386 if (labels.fall_through == labels.false_label) { | 384 if (true_condition == NEXT_IS_TRUE) { |
| 387 // If the next block is the false successor, fall through to it. | |
| 388 __ Jump(labels.true_label); | 385 __ Jump(labels.true_label); |
| 386 if (labels.fall_through != labels.false_label) { |
| 387 __ Jump(labels.false_label); |
| 388 } |
| 389 } else { | 389 } else { |
| 390 // If the next block is not the false successor, branch to it. | 390 ASSERT(true_condition == NEXT_IS_FALSE); |
| 391 __ Jump(labels.false_label); | 391 __ Jump(labels.false_label); |
| 392 | |
| 393 // Fall through or jump to the true successor. | |
| 394 if (labels.fall_through != labels.true_label) { | 392 if (labels.fall_through != labels.true_label) { |
| 395 __ Jump(labels.true_label); | 393 __ Jump(labels.true_label); |
| 396 } | 394 } |
| 397 } | 395 } |
| 398 } | 396 } |
| 399 | 397 |
| 400 | 398 |
| 401 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 399 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 402 BranchLabels labels) { | 400 BranchLabels labels) { |
| 403 ASSERT((kind() == Token::kNE_STRICT) || | 401 ASSERT((kind() == Token::kNE_STRICT) || |
| 404 (kind() == Token::kEQ_STRICT)); | 402 (kind() == Token::kEQ_STRICT)); |
| 405 | 403 |
| 404 Token::Kind comparison; |
| 405 Condition condition; |
| 406 if (labels.fall_through == labels.false_label) { |
| 407 condition = NEXT_IS_TRUE; |
| 408 comparison = kind(); |
| 409 } else { |
| 410 // Flip comparision to save a jump. |
| 411 condition = NEXT_IS_FALSE; |
| 412 comparison = (kind() == Token::kEQ_STRICT) ? Token::kNE_STRICT |
| 413 : Token::kEQ_STRICT; |
| 414 } |
| 415 |
| 406 if (!compiler->is_optimizing()) { | 416 if (!compiler->is_optimizing()) { |
| 407 const Bytecode::Opcode eq_op = needs_number_check() ? | 417 const Bytecode::Opcode eq_op = needs_number_check() ? |
| 408 Bytecode::kIfEqStrictNumTOS : Bytecode::kIfEqStrictTOS; | 418 Bytecode::kIfEqStrictNumTOS : Bytecode::kIfEqStrictTOS; |
| 409 const Bytecode::Opcode ne_op = needs_number_check() ? | 419 const Bytecode::Opcode ne_op = needs_number_check() ? |
| 410 Bytecode::kIfNeStrictNumTOS : Bytecode::kIfNeStrictTOS; | 420 Bytecode::kIfNeStrictNumTOS : Bytecode::kIfNeStrictTOS; |
| 411 | 421 __ Emit(comparison == Token::kEQ_STRICT ? eq_op : ne_op); |
| 412 if (kind() == Token::kEQ_STRICT) { | |
| 413 __ Emit((labels.fall_through == labels.false_label) ? eq_op : ne_op); | |
| 414 } else { | |
| 415 __ Emit((labels.fall_through == labels.false_label) ? ne_op : eq_op); | |
| 416 } | |
| 417 } else { | 422 } else { |
| 418 const Bytecode::Opcode eq_op = needs_number_check() ? | 423 const Bytecode::Opcode eq_op = needs_number_check() ? |
| 419 Bytecode::kIfEqStrictNum : Bytecode::kIfEqStrict; | 424 Bytecode::kIfEqStrictNum : Bytecode::kIfEqStrict; |
| 420 const Bytecode::Opcode ne_op = needs_number_check() ? | 425 const Bytecode::Opcode ne_op = needs_number_check() ? |
| 421 Bytecode::kIfNeStrictNum : Bytecode::kIfNeStrict; | 426 Bytecode::kIfNeStrictNum : Bytecode::kIfNeStrict; |
| 422 | 427 __ Emit(Bytecode::Encode( |
| 423 if (kind() == Token::kEQ_STRICT) { | 428 (comparison == Token::kEQ_STRICT) ? eq_op : ne_op, |
| 424 __ Emit(Bytecode::Encode( | 429 locs()->in(0).reg(), |
| 425 (labels.fall_through == labels.false_label) ? eq_op : ne_op, | 430 locs()->in(1).reg())); |
| 426 locs()->in(0).reg(), | |
| 427 locs()->in(1).reg())); | |
| 428 } else { | |
| 429 __ Emit(Bytecode::Encode( | |
| 430 (labels.fall_through == labels.false_label) ? ne_op : eq_op, | |
| 431 locs()->in(0).reg(), | |
| 432 locs()->in(1).reg())); | |
| 433 } | |
| 434 } | 431 } |
| 435 | 432 |
| 436 if (needs_number_check() && token_pos().IsReal()) { | 433 if (needs_number_check() && token_pos().IsReal()) { |
| 437 compiler->RecordSafepoint(locs()); | 434 compiler->RecordSafepoint(locs()); |
| 438 compiler->AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 435 compiler->AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
| 439 Thread::kNoDeoptId, | 436 Thread::kNoDeoptId, |
| 440 token_pos()); | 437 token_pos()); |
| 441 } | 438 } |
| 442 return EQ; | 439 |
| 440 return condition; |
| 443 } | 441 } |
| 444 | 442 |
| 445 | 443 |
| 446 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 444 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 447 BranchInstr* branch) { | 445 BranchInstr* branch) { |
| 448 ASSERT((kind() == Token::kEQ_STRICT) || | 446 ASSERT((kind() == Token::kEQ_STRICT) || |
| 449 (kind() == Token::kNE_STRICT)); | 447 (kind() == Token::kNE_STRICT)); |
| 450 | 448 |
| 451 BranchLabels labels = compiler->CreateBranchLabels(branch); | 449 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 452 Condition true_condition = EmitComparisonCode(compiler, labels); | 450 Condition true_condition = EmitComparisonCode(compiler, labels); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 506 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 509 } | 507 } |
| 510 // We can fall through if the successor is the next block in the list. | 508 // We can fall through if the successor is the next block in the list. |
| 511 // Otherwise, we need a jump. | 509 // Otherwise, we need a jump. |
| 512 if (!compiler->CanFallThroughTo(successor())) { | 510 if (!compiler->CanFallThroughTo(successor())) { |
| 513 __ Jump(compiler->GetJumpLabel(successor())); | 511 __ Jump(compiler->GetJumpLabel(successor())); |
| 514 } | 512 } |
| 515 } | 513 } |
| 516 | 514 |
| 517 | 515 |
| 516 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 517 BranchLabels labels) { |
| 518 ASSERT((kind() == Token::kEQ) || |
| 519 (kind() == Token::kNE)); |
| 520 Register left = locs()->in(0).reg(); |
| 521 Register right = locs()->in(1).reg(); |
| 522 __ TestSmi(left, right); |
| 523 return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE; |
| 524 } |
| 525 |
| 526 |
| 527 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 528 BranchInstr* branch) { |
| 529 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 530 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 531 EmitBranchOnCondition(compiler, true_condition, labels); |
| 532 } |
| 533 |
| 534 |
| 535 EMIT_NATIVE_CODE(TestSmi, |
| 536 2, |
| 537 Location::RequiresRegister(), |
| 538 LocationSummary::kNoCall) { |
| 539 // Never emitted outside of the BranchInstr. |
| 540 UNREACHABLE(); |
| 541 } |
| 542 |
| 543 |
| 518 EMIT_NATIVE_CODE(CreateArray, | 544 EMIT_NATIVE_CODE(CreateArray, |
| 519 2, Location::RequiresRegister(), | 545 2, Location::RequiresRegister(), |
| 520 LocationSummary::kCall) { | 546 LocationSummary::kCall) { |
| 521 if (compiler->is_optimizing()) { | 547 if (compiler->is_optimizing()) { |
| 522 __ Push(locs()->in(0).reg()); | 548 __ Push(locs()->in(0).reg()); |
| 523 __ Push(locs()->in(1).reg()); | 549 __ Push(locs()->in(1).reg()); |
| 524 } | 550 } |
| 525 __ CreateArrayTOS(); | 551 __ CreateArrayTOS(); |
| 526 compiler->RecordSafepoint(locs()); | 552 compiler->RecordSafepoint(locs()); |
| 527 if (compiler->is_optimizing()) { | 553 if (compiler->is_optimizing()) { |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 __ BitNot(locs()->out(0).reg(), locs()->in(0).reg()); | 1084 __ BitNot(locs()->out(0).reg(), locs()->in(0).reg()); |
| 1059 break; | 1085 break; |
| 1060 default: | 1086 default: |
| 1061 UNREACHABLE(); | 1087 UNREACHABLE(); |
| 1062 } | 1088 } |
| 1063 } | 1089 } |
| 1064 | 1090 |
| 1065 } // namespace dart | 1091 } // namespace dart |
| 1066 | 1092 |
| 1067 #endif // defined TARGET_ARCH_DBC | 1093 #endif // defined TARGET_ARCH_DBC |
| OLD | NEW |