diff options
author | Refael Ackermann <refack@gmail.com> | 2014-09-29 13:20:04 +0400 |
---|---|---|
committer | Fedor Indutny <fedor@indutny.com> | 2014-10-08 15:35:57 +0400 |
commit | 939278ac059b44439d41aab12bf552c8ae3c52d0 (patch) | |
tree | 86c586915a96d308b1b04de679a8ae293caf3e41 /deps/v8/test/cctest/compiler/test-instruction.cc | |
parent | 4412a71d76a0fa002f627ec21d2337e089da6764 (diff) | |
download | node-new-939278ac059b44439d41aab12bf552c8ae3c52d0.tar.gz |
deps: update v8 to 3.28.73
Reviewed-By: Fedor Indutny <fedor@indutny.com>
PR-URL: https://github.com/joyent/node/pull/8476
Diffstat (limited to 'deps/v8/test/cctest/compiler/test-instruction.cc')
-rw-r--r-- | deps/v8/test/cctest/compiler/test-instruction.cc | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/deps/v8/test/cctest/compiler/test-instruction.cc b/deps/v8/test/cctest/compiler/test-instruction.cc new file mode 100644 index 0000000000..bc9f4c7723 --- /dev/null +++ b/deps/v8/test/cctest/compiler/test-instruction.cc @@ -0,0 +1,350 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/v8.h" +#include "test/cctest/cctest.h" + +#include "src/compiler/code-generator.h" +#include "src/compiler/common-operator.h" +#include "src/compiler/graph.h" +#include "src/compiler/instruction.h" +#include "src/compiler/machine-operator.h" +#include "src/compiler/node.h" +#include "src/compiler/operator.h" +#include "src/compiler/schedule.h" +#include "src/compiler/scheduler.h" +#include "src/lithium.h" + +using namespace v8::internal; +using namespace v8::internal::compiler; + +typedef v8::internal::compiler::Instruction TestInstr; +typedef v8::internal::compiler::InstructionSequence TestInstrSeq; + +// A testing helper for the register code abstraction. +class InstructionTester : public HandleAndZoneScope { + public: // We're all friends here. + InstructionTester() + : isolate(main_isolate()), + graph(zone()), + schedule(zone()), + info(static_cast<HydrogenCodeStub*>(NULL), main_isolate()), + linkage(&info), + common(zone()), + machine(zone(), kMachineWord32), + code(NULL) {} + + ~InstructionTester() { delete code; } + + Isolate* isolate; + Graph graph; + Schedule schedule; + CompilationInfoWithZone info; + Linkage linkage; + CommonOperatorBuilder common; + MachineOperatorBuilder machine; + TestInstrSeq* code; + + Zone* zone() { return main_zone(); } + + void allocCode() { + if (schedule.rpo_order()->size() == 0) { + // Compute the RPO order. + Scheduler::ComputeSpecialRPO(&schedule); + DCHECK(schedule.rpo_order()->size() > 0); + } + code = new TestInstrSeq(&linkage, &graph, &schedule); + } + + Node* Int32Constant(int32_t val) { + Node* node = graph.NewNode(common.Int32Constant(val)); + schedule.AddNode(schedule.entry(), node); + return node; + } + + Node* Float64Constant(double val) { + Node* node = graph.NewNode(common.Float64Constant(val)); + schedule.AddNode(schedule.entry(), node); + return node; + } + + Node* Parameter(int32_t which) { + Node* node = graph.NewNode(common.Parameter(which)); + schedule.AddNode(schedule.entry(), node); + return node; + } + + Node* NewNode(BasicBlock* block) { + Node* node = graph.NewNode(common.Int32Constant(111)); + schedule.AddNode(block, node); + return node; + } + + int NewInstr(BasicBlock* block) { + InstructionCode opcode = static_cast<InstructionCode>(110); + TestInstr* instr = TestInstr::New(zone(), opcode); + return code->AddInstruction(instr, block); + } + + UnallocatedOperand* NewUnallocated(int vreg) { + UnallocatedOperand* unallocated = + new (zone()) UnallocatedOperand(UnallocatedOperand::ANY); + unallocated->set_virtual_register(vreg); + return unallocated; + } +}; + + +TEST(InstructionBasic) { + InstructionTester R; + + for (int i = 0; i < 10; i++) { + R.Int32Constant(i); // Add some nodes to the graph. + } + + BasicBlock* last = R.schedule.entry(); + for (int i = 0; i < 5; i++) { + BasicBlock* block = R.schedule.NewBasicBlock(); + R.schedule.AddGoto(last, block); + last = block; + } + + R.allocCode(); + + CHECK_EQ(R.graph.NodeCount(), R.code->ValueCount()); + + BasicBlockVector* blocks = R.schedule.rpo_order(); + CHECK_EQ(static_cast<int>(blocks->size()), R.code->BasicBlockCount()); + + int index = 0; + for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end(); + i++, index++) { + BasicBlock* block = *i; + CHECK_EQ(block, R.code->BlockAt(index)); + CHECK_EQ(-1, R.code->GetLoopEnd(block)); + } +} + + +TEST(InstructionGetBasicBlock) { + InstructionTester R; + + BasicBlock* b0 = R.schedule.entry(); + BasicBlock* b1 = R.schedule.NewBasicBlock(); + BasicBlock* b2 = R.schedule.NewBasicBlock(); + BasicBlock* b3 = R.schedule.exit(); + + R.schedule.AddGoto(b0, b1); + R.schedule.AddGoto(b1, b2); + R.schedule.AddGoto(b2, b3); + + R.allocCode(); + + R.code->StartBlock(b0); + int i0 = R.NewInstr(b0); + int i1 = R.NewInstr(b0); + R.code->EndBlock(b0); + R.code->StartBlock(b1); + int i2 = R.NewInstr(b1); + int i3 = R.NewInstr(b1); + int i4 = R.NewInstr(b1); + int i5 = R.NewInstr(b1); + R.code->EndBlock(b1); + R.code->StartBlock(b2); + int i6 = R.NewInstr(b2); + int i7 = R.NewInstr(b2); + int i8 = R.NewInstr(b2); + R.code->EndBlock(b2); + R.code->StartBlock(b3); + R.code->EndBlock(b3); + + CHECK_EQ(b0, R.code->GetBasicBlock(i0)); + CHECK_EQ(b0, R.code->GetBasicBlock(i1)); + + CHECK_EQ(b1, R.code->GetBasicBlock(i2)); + CHECK_EQ(b1, R.code->GetBasicBlock(i3)); + CHECK_EQ(b1, R.code->GetBasicBlock(i4)); + CHECK_EQ(b1, R.code->GetBasicBlock(i5)); + + CHECK_EQ(b2, R.code->GetBasicBlock(i6)); + CHECK_EQ(b2, R.code->GetBasicBlock(i7)); + CHECK_EQ(b2, R.code->GetBasicBlock(i8)); + + CHECK_EQ(b0, R.code->GetBasicBlock(b0->first_instruction_index())); + CHECK_EQ(b0, R.code->GetBasicBlock(b0->last_instruction_index())); + + CHECK_EQ(b1, R.code->GetBasicBlock(b1->first_instruction_index())); + CHECK_EQ(b1, R.code->GetBasicBlock(b1->last_instruction_index())); + + CHECK_EQ(b2, R.code->GetBasicBlock(b2->first_instruction_index())); + CHECK_EQ(b2, R.code->GetBasicBlock(b2->last_instruction_index())); + + CHECK_EQ(b3, R.code->GetBasicBlock(b3->first_instruction_index())); + CHECK_EQ(b3, R.code->GetBasicBlock(b3->last_instruction_index())); +} + + +TEST(InstructionIsGapAt) { + InstructionTester R; + + BasicBlock* b0 = R.schedule.entry(); + R.schedule.AddReturn(b0, R.Int32Constant(1)); + + R.allocCode(); + TestInstr* i0 = TestInstr::New(R.zone(), 100); + TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl(); + R.code->StartBlock(b0); + R.code->AddInstruction(i0, b0); + R.code->AddInstruction(g, b0); + R.code->EndBlock(b0); + + CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart()); + + CHECK_EQ(true, R.code->IsGapAt(0)); // Label + CHECK_EQ(true, R.code->IsGapAt(1)); // Gap + CHECK_EQ(false, R.code->IsGapAt(2)); // i0 + CHECK_EQ(true, R.code->IsGapAt(3)); // Gap + CHECK_EQ(true, R.code->IsGapAt(4)); // Gap + CHECK_EQ(false, R.code->IsGapAt(5)); // g +} + + +TEST(InstructionIsGapAt2) { + InstructionTester R; + + BasicBlock* b0 = R.schedule.entry(); + BasicBlock* b1 = R.schedule.exit(); + R.schedule.AddGoto(b0, b1); + R.schedule.AddReturn(b1, R.Int32Constant(1)); + + R.allocCode(); + TestInstr* i0 = TestInstr::New(R.zone(), 100); + TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl(); + R.code->StartBlock(b0); + R.code->AddInstruction(i0, b0); + R.code->AddInstruction(g, b0); + R.code->EndBlock(b0); + + TestInstr* i1 = TestInstr::New(R.zone(), 102); + TestInstr* g1 = TestInstr::New(R.zone(), 104)->MarkAsControl(); + R.code->StartBlock(b1); + R.code->AddInstruction(i1, b1); + R.code->AddInstruction(g1, b1); + R.code->EndBlock(b1); + + CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart()); + + CHECK_EQ(true, R.code->IsGapAt(0)); // Label + CHECK_EQ(true, R.code->IsGapAt(1)); // Gap + CHECK_EQ(false, R.code->IsGapAt(2)); // i0 + CHECK_EQ(true, R.code->IsGapAt(3)); // Gap + CHECK_EQ(true, R.code->IsGapAt(4)); // Gap + CHECK_EQ(false, R.code->IsGapAt(5)); // g + + CHECK_EQ(true, R.code->InstructionAt(6)->IsBlockStart()); + + CHECK_EQ(true, R.code->IsGapAt(6)); // Label + CHECK_EQ(true, R.code->IsGapAt(7)); // Gap + CHECK_EQ(false, R.code->IsGapAt(8)); // i1 + CHECK_EQ(true, R.code->IsGapAt(9)); // Gap + CHECK_EQ(true, R.code->IsGapAt(10)); // Gap + CHECK_EQ(false, R.code->IsGapAt(11)); // g1 +} + + +TEST(InstructionAddGapMove) { + InstructionTester R; + + BasicBlock* b0 = R.schedule.entry(); + R.schedule.AddReturn(b0, R.Int32Constant(1)); + + R.allocCode(); + TestInstr* i0 = TestInstr::New(R.zone(), 100); + TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl(); + R.code->StartBlock(b0); + R.code->AddInstruction(i0, b0); + R.code->AddInstruction(g, b0); + R.code->EndBlock(b0); + + CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart()); + + CHECK_EQ(true, R.code->IsGapAt(0)); // Label + CHECK_EQ(true, R.code->IsGapAt(1)); // Gap + CHECK_EQ(false, R.code->IsGapAt(2)); // i0 + CHECK_EQ(true, R.code->IsGapAt(3)); // Gap + CHECK_EQ(true, R.code->IsGapAt(4)); // Gap + CHECK_EQ(false, R.code->IsGapAt(5)); // g + + int indexes[] = {0, 1, 3, 4, -1}; + for (int i = 0; indexes[i] >= 0; i++) { + int index = indexes[i]; + + UnallocatedOperand* op1 = R.NewUnallocated(index + 6); + UnallocatedOperand* op2 = R.NewUnallocated(index + 12); + + R.code->AddGapMove(index, op1, op2); + GapInstruction* gap = R.code->GapAt(index); + ParallelMove* move = gap->GetParallelMove(GapInstruction::START); + CHECK_NE(NULL, move); + const ZoneList<MoveOperands>* move_operands = move->move_operands(); + CHECK_EQ(1, move_operands->length()); + MoveOperands* cur = &move_operands->at(0); + CHECK_EQ(op1, cur->source()); + CHECK_EQ(op2, cur->destination()); + } +} + + +TEST(InstructionOperands) { + Zone zone(CcTest::InitIsolateOnce()); + + { + TestInstr* i = TestInstr::New(&zone, 101); + CHECK_EQ(0, static_cast<int>(i->OutputCount())); + CHECK_EQ(0, static_cast<int>(i->InputCount())); + CHECK_EQ(0, static_cast<int>(i->TempCount())); + } + + InstructionOperand* outputs[] = { + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER), + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER), + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER), + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)}; + + InstructionOperand* inputs[] = { + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER), + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER), + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER), + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)}; + + InstructionOperand* temps[] = { + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER), + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER), + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER), + new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)}; + + for (size_t i = 0; i < ARRAY_SIZE(outputs); i++) { + for (size_t j = 0; j < ARRAY_SIZE(inputs); j++) { + for (size_t k = 0; k < ARRAY_SIZE(temps); k++) { + TestInstr* m = + TestInstr::New(&zone, 101, i, outputs, j, inputs, k, temps); + CHECK(i == m->OutputCount()); + CHECK(j == m->InputCount()); + CHECK(k == m->TempCount()); + + for (size_t z = 0; z < i; z++) { + CHECK_EQ(outputs[z], m->OutputAt(z)); + } + + for (size_t z = 0; z < j; z++) { + CHECK_EQ(inputs[z], m->InputAt(z)); + } + + for (size_t z = 0; z < k; z++) { + CHECK_EQ(temps[z], m->TempAt(z)); + } + } + } + } +} |