| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 M(ExtractNthOutput) \ | 95 M(ExtractNthOutput) \ |
| 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(TestSmi) \ | |
| 106 M(RelationalOp) \ | 105 M(RelationalOp) \ |
| 107 M(EqualityCompare) \ | 106 M(EqualityCompare) \ |
| 108 M(LoadIndexed) | 107 M(LoadIndexed) |
| 109 | 108 |
| 110 // Location summaries actually are not used by the unoptimizing DBC compiler | 109 // Location summaries actually are not used by the unoptimizing DBC compiler |
| 111 // because we don't allocate any registers. | 110 // because we don't allocate any registers. |
| 112 static LocationSummary* CreateLocationSummary( | 111 static LocationSummary* CreateLocationSummary( |
| 113 Zone* zone, | 112 Zone* zone, |
| 114 intptr_t num_inputs, | 113 intptr_t num_inputs, |
| 115 Location output = Location::NoLocation(), | 114 Location output = Location::NoLocation(), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 UNIMPLEMENTED(); \ | 150 UNIMPLEMENTED(); \ |
| 152 } | 151 } |
| 153 | 152 |
| 154 #define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name) \ | 153 #define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name) \ |
| 155 void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) { \ | 154 void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) { \ |
| 156 UNIMPLEMENTED(); \ | 155 UNIMPLEMENTED(); \ |
| 157 } \ | 156 } \ |
| 158 Condition Name##Instr::EmitComparisonCode(FlowGraphCompiler*, \ | 157 Condition Name##Instr::EmitComparisonCode(FlowGraphCompiler*, \ |
| 159 BranchLabels) { \ | 158 BranchLabels) { \ |
| 160 UNIMPLEMENTED(); \ | 159 UNIMPLEMENTED(); \ |
| 161 return EQ; \ | 160 return NEXT_IS_TRUE; \ |
| 162 } | 161 } |
| 163 | 162 |
| 164 #define DEFINE_UNIMPLEMENTED(Name) \ | 163 #define DEFINE_UNIMPLEMENTED(Name) \ |
| 165 DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name) \ | 164 DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name) \ |
| 166 DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) \ | 165 DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) \ |
| 167 | 166 |
| 168 FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED) | 167 FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED) |
| 169 | 168 |
| 170 #undef DEFINE_UNIMPLEMENTED | 169 #undef DEFINE_UNIMPLEMENTED |
| 171 | 170 |
| 172 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestCids) | 171 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestCids) |
| 173 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestSmi) | |
| 174 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(RelationalOp) | 172 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(RelationalOp) |
| 175 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare) | 173 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare) |
| 176 | 174 |
| 177 | 175 |
| 178 EMIT_NATIVE_CODE(InstanceOf, 2, Location::SameAsFirstInput(), | 176 EMIT_NATIVE_CODE(InstanceOf, 2, Location::SameAsFirstInput(), |
| 179 LocationSummary::kCall) { | 177 LocationSummary::kCall) { |
| 180 SubtypeTestCache& test_cache = SubtypeTestCache::Handle(); | 178 SubtypeTestCache& test_cache = SubtypeTestCache::Handle(); |
| 181 if (!type().IsVoidType() && type().IsInstantiated()) { | 179 if (!type().IsVoidType() && type().IsInstantiated()) { |
| 182 test_cache = SubtypeTestCache::New(); | 180 test_cache = SubtypeTestCache::New(); |
| 183 } | 181 } |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 | 373 |
| 376 if (compiler->is_optimizing()) { | 374 if (compiler->is_optimizing()) { |
| 377 __ PopLocal(locs()->out(0).reg()); | 375 __ PopLocal(locs()->out(0).reg()); |
| 378 } | 376 } |
| 379 } | 377 } |
| 380 | 378 |
| 381 | 379 |
| 382 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 380 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 383 Condition true_condition, | 381 Condition true_condition, |
| 384 BranchLabels labels) { | 382 BranchLabels labels) { |
| 385 if (labels.fall_through == labels.false_label) { | 383 if (true_condition == NEXT_IS_TRUE) { |
| 386 // If the next block is the false successor, fall through to it. | |
| 387 __ Jump(labels.true_label); | 384 __ Jump(labels.true_label); |
| 385 if (labels.fall_through != labels.false_label) { |
| 386 __ Jump(labels.false_label); |
| 387 } |
| 388 } else { | 388 } else { |
| 389 // If the next block is not the false successor, branch to it. | 389 ASSERT(true_condition == NEXT_IS_FALSE); |
| 390 __ Jump(labels.false_label); | 390 __ Jump(labels.false_label); |
| 391 | |
| 392 // Fall through or jump to the true successor. | |
| 393 if (labels.fall_through != labels.true_label) { | 391 if (labels.fall_through != labels.true_label) { |
| 394 __ Jump(labels.true_label); | 392 __ Jump(labels.true_label); |
| 395 } | 393 } |
| 396 } | 394 } |
| 397 } | 395 } |
| 398 | 396 |
| 399 | 397 |
| 400 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 398 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 401 BranchLabels labels) { | 399 BranchLabels labels) { |
| 402 ASSERT((kind() == Token::kNE_STRICT) || | 400 ASSERT((kind() == Token::kNE_STRICT) || |
| 403 (kind() == Token::kEQ_STRICT)); | 401 (kind() == Token::kEQ_STRICT)); |
| 404 | 402 |
| 403 Token::Kind comparison; |
| 404 Condition condition; |
| 405 if (labels.fall_through == labels.false_label) { |
| 406 condition = NEXT_IS_TRUE; |
| 407 comparison = kind(); |
| 408 } else { |
| 409 // Flip comparision to save a jump. |
| 410 condition = NEXT_IS_FALSE; |
| 411 comparison = (kind() == Token::kEQ_STRICT) ? Token::kNE_STRICT |
| 412 : Token::kEQ_STRICT; |
| 413 } |
| 414 |
| 405 if (!compiler->is_optimizing()) { | 415 if (!compiler->is_optimizing()) { |
| 406 const Bytecode::Opcode eq_op = needs_number_check() ? | 416 const Bytecode::Opcode eq_op = needs_number_check() ? |
| 407 Bytecode::kIfEqStrictNumTOS : Bytecode::kIfEqStrictTOS; | 417 Bytecode::kIfEqStrictNumTOS : Bytecode::kIfEqStrictTOS; |
| 408 const Bytecode::Opcode ne_op = needs_number_check() ? | 418 const Bytecode::Opcode ne_op = needs_number_check() ? |
| 409 Bytecode::kIfNeStrictNumTOS : Bytecode::kIfNeStrictTOS; | 419 Bytecode::kIfNeStrictNumTOS : Bytecode::kIfNeStrictTOS; |
| 410 | 420 __ Emit(comparison == Token::kEQ_STRICT ? eq_op : ne_op); |
| 411 if (kind() == Token::kEQ_STRICT) { | |
| 412 __ Emit((labels.fall_through == labels.false_label) ? eq_op : ne_op); | |
| 413 } else { | |
| 414 __ Emit((labels.fall_through == labels.false_label) ? ne_op : eq_op); | |
| 415 } | |
| 416 } else { | 421 } else { |
| 417 const Bytecode::Opcode eq_op = needs_number_check() ? | 422 const Bytecode::Opcode eq_op = needs_number_check() ? |
| 418 Bytecode::kIfEqStrictNum : Bytecode::kIfEqStrict; | 423 Bytecode::kIfEqStrictNum : Bytecode::kIfEqStrict; |
| 419 const Bytecode::Opcode ne_op = needs_number_check() ? | 424 const Bytecode::Opcode ne_op = needs_number_check() ? |
| 420 Bytecode::kIfNeStrictNum : Bytecode::kIfNeStrict; | 425 Bytecode::kIfNeStrictNum : Bytecode::kIfNeStrict; |
| 421 | 426 __ Emit(Bytecode::Encode( |
| 422 if (kind() == Token::kEQ_STRICT) { | 427 (comparison == Token::kEQ_STRICT) ? eq_op : ne_op, |
| 423 __ Emit(Bytecode::Encode( | 428 locs()->in(0).reg(), |
| 424 (labels.fall_through == labels.false_label) ? eq_op : ne_op, | 429 locs()->in(1).reg())); |
| 425 locs()->in(0).reg(), | |
| 426 locs()->in(1).reg())); | |
| 427 } else { | |
| 428 __ Emit(Bytecode::Encode( | |
| 429 (labels.fall_through == labels.false_label) ? ne_op : eq_op, | |
| 430 locs()->in(0).reg(), | |
| 431 locs()->in(1).reg())); | |
| 432 } | |
| 433 } | 430 } |
| 434 | 431 |
| 435 if (needs_number_check() && token_pos().IsReal()) { | 432 if (needs_number_check() && token_pos().IsReal()) { |
| 436 compiler->RecordSafepoint(locs()); | 433 compiler->RecordSafepoint(locs()); |
| 437 compiler->AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 434 compiler->AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
| 438 Thread::kNoDeoptId, | 435 Thread::kNoDeoptId, |
| 439 token_pos()); | 436 token_pos()); |
| 440 } | 437 } |
| 441 return EQ; | 438 |
| 439 return condition; |
| 442 } | 440 } |
| 443 | 441 |
| 444 | 442 |
| 445 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 443 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 446 BranchInstr* branch) { | 444 BranchInstr* branch) { |
| 447 ASSERT((kind() == Token::kEQ_STRICT) || | 445 ASSERT((kind() == Token::kEQ_STRICT) || |
| 448 (kind() == Token::kNE_STRICT)); | 446 (kind() == Token::kNE_STRICT)); |
| 449 | 447 |
| 450 BranchLabels labels = compiler->CreateBranchLabels(branch); | 448 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 451 Condition true_condition = EmitComparisonCode(compiler, labels); | 449 Condition true_condition = EmitComparisonCode(compiler, labels); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 512 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 515 } | 513 } |
| 516 // We can fall through if the successor is the next block in the list. | 514 // We can fall through if the successor is the next block in the list. |
| 517 // Otherwise, we need a jump. | 515 // Otherwise, we need a jump. |
| 518 if (!compiler->CanFallThroughTo(successor())) { | 516 if (!compiler->CanFallThroughTo(successor())) { |
| 519 __ Jump(compiler->GetJumpLabel(successor())); | 517 __ Jump(compiler->GetJumpLabel(successor())); |
| 520 } | 518 } |
| 521 } | 519 } |
| 522 | 520 |
| 523 | 521 |
| 522 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 523 BranchLabels labels) { |
| 524 ASSERT((kind() == Token::kEQ) || |
| 525 (kind() == Token::kNE)); |
| 526 Register left = locs()->in(0).reg(); |
| 527 Register right = locs()->in(1).reg(); |
| 528 __ TestSmi(left, right); |
| 529 return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE; |
| 530 } |
| 531 |
| 532 |
| 533 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 534 BranchInstr* branch) { |
| 535 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 536 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 537 EmitBranchOnCondition(compiler, true_condition, labels); |
| 538 } |
| 539 |
| 540 |
| 541 EMIT_NATIVE_CODE(TestSmi, |
| 542 2, |
| 543 Location::RequiresRegister(), |
| 544 LocationSummary::kNoCall) { |
| 545 // Never emitted outside of the BranchInstr. |
| 546 UNREACHABLE(); |
| 547 } |
| 548 |
| 549 |
| 524 EMIT_NATIVE_CODE(CreateArray, | 550 EMIT_NATIVE_CODE(CreateArray, |
| 525 2, Location::RequiresRegister(), | 551 2, Location::RequiresRegister(), |
| 526 LocationSummary::kCall) { | 552 LocationSummary::kCall) { |
| 527 if (compiler->is_optimizing()) { | 553 if (compiler->is_optimizing()) { |
| 528 __ Push(locs()->in(0).reg()); | 554 __ Push(locs()->in(0).reg()); |
| 529 __ Push(locs()->in(1).reg()); | 555 __ Push(locs()->in(1).reg()); |
| 530 } | 556 } |
| 531 __ CreateArrayTOS(); | 557 __ CreateArrayTOS(); |
| 532 compiler->RecordSafepoint(locs()); | 558 compiler->RecordSafepoint(locs()); |
| 533 if (compiler->is_optimizing()) { | 559 if (compiler->is_optimizing()) { |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 __ BitNot(locs()->out(0).reg(), locs()->in(0).reg()); | 1159 __ BitNot(locs()->out(0).reg(), locs()->in(0).reg()); |
| 1134 break; | 1160 break; |
| 1135 default: | 1161 default: |
| 1136 UNREACHABLE(); | 1162 UNREACHABLE(); |
| 1137 } | 1163 } |
| 1138 } | 1164 } |
| 1139 | 1165 |
| 1140 } // namespace dart | 1166 } // namespace dart |
| 1141 | 1167 |
| 1142 #endif // defined TARGET_ARCH_DBC | 1168 #endif // defined TARGET_ARCH_DBC |
| OLD | NEW |