Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "src/v8.h" | |
| 6 | |
| 7 #include "src/interpreter/bytecode-array-writer.h" | |
| 8 #include "src/interpreter/source-position-table.h" | |
| 9 #include "src/isolate.h" | |
| 10 #include "src/utils.h" | |
| 11 #include "test/unittests/interpreter/bytecode-utils.h" | |
| 12 #include "test/unittests/test-utils.h" | |
| 13 | |
| 14 namespace v8 { | |
| 15 namespace internal { | |
| 16 namespace interpreter { | |
| 17 | |
| 18 class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone { | |
| 19 public: | |
| 20 BytecodeArrayWriterUnittest() | |
| 21 : source_position_builder_(isolate(), zone()), | |
| 22 bytecode_array_writer_(zone(), &source_position_builder_) {} | |
| 23 ~BytecodeArrayWriterUnittest() override {} | |
| 24 | |
| 25 SourcePositionTableBuilder* source_position_builder() { | |
| 26 return &source_position_builder_; | |
| 27 } | |
| 28 BytecodeArrayWriter* writer() { return &bytecode_array_writer_; } | |
| 29 | |
| 30 private: | |
| 31 SourcePositionTableBuilder source_position_builder_; | |
| 32 BytecodeArrayWriter bytecode_array_writer_; | |
| 33 }; | |
| 34 | |
| 35 TEST_F(BytecodeArrayWriterUnittest, SimpleExample) { | |
| 36 CHECK_EQ(writer()->bytecodes()->size(), 0); | |
| 37 | |
| 38 BytecodeNode node0(Bytecode::kStackCheck); | |
| 39 node0.source_info().Update({10, false}); | |
| 40 writer()->Write(&node0); | |
| 41 CHECK_EQ(writer()->bytecodes()->size(), 1); | |
| 42 CHECK_EQ(writer()->GetMeasuredFrameSize(), 0); | |
| 43 | |
| 44 BytecodeNode node1(Bytecode::kLdaSmi, 0xff, OperandScale::kSingle); | |
| 45 node1.source_info().Update({55, true}); | |
| 46 writer()->Write(&node1); | |
| 47 CHECK_EQ(writer()->bytecodes()->size(), 3); | |
| 48 CHECK_EQ(writer()->GetMeasuredFrameSize(), 0); | |
| 49 | |
| 50 BytecodeNode node2(Bytecode::kLdar, Register(1).ToOperand(), | |
| 51 OperandScale::kDouble); | |
| 52 writer()->Write(&node2); | |
| 53 CHECK_EQ(writer()->bytecodes()->size(), 7); | |
| 54 CHECK_EQ(writer()->GetMeasuredFrameSize(), 2 * kPointerSize); | |
| 55 | |
| 56 BytecodeNode node3(Bytecode::kReturn); | |
| 57 node3.source_info().Update({70, true}); | |
| 58 writer()->Write(&node3); | |
| 59 CHECK_EQ(writer()->bytecodes()->size(), 8); | |
| 60 CHECK_EQ(writer()->GetMeasuredFrameSize(), 2 * kPointerSize); | |
| 61 | |
| 62 static const uint8_t bytes[] = {B(StackCheck), B(LdaSmi), U8(0xff), B(Wide), | |
| 63 B(Ldar), R16(1), B(Return)}; | |
| 64 CHECK_EQ(writer()->bytecodes()->size(), arraysize(bytes)); | |
| 65 for (size_t i = 0; i < arraysize(bytes); ++i) { | |
| 66 CHECK_EQ(writer()->bytecodes()->at(i), bytes[i]); | |
| 67 } | |
| 68 | |
| 69 CHECK_EQ(writer()->FlushForOffset(), arraysize(bytes)); | |
| 70 writer()->FlushBasicBlock(); | |
| 71 CHECK_EQ(writer()->bytecodes()->size(), arraysize(bytes)); | |
| 72 | |
| 73 PositionTableEntry expected_positions[] = { | |
| 74 {0, 10, false}, {1, 55, true}, {7, 70, true}}; | |
| 75 Handle<ByteArray> source_positions = | |
| 76 source_position_builder()->ToSourcePositionTable(); | |
| 77 SourcePositionTableIterator source_iterator(*source_positions); | |
| 78 for (size_t i = 0; i < arraysize(expected_positions); ++i) { | |
| 79 const PositionTableEntry& expected = expected_positions[i]; | |
| 80 CHECK_EQ(source_iterator.bytecode_offset(), expected.bytecode_offset); | |
| 81 CHECK_EQ(source_iterator.source_position(), expected.source_position); | |
| 82 CHECK_EQ(source_iterator.is_statement(), expected.is_statement); | |
| 83 source_iterator.Advance(); | |
| 84 } | |
| 85 CHECK(source_iterator.done()); | |
| 86 } | |
| 87 | |
| 88 | |
| 89 TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { | |
| 90 static const uint8_t expected_bytes[] = { | |
| 91 // clang-format off | |
|
rmcilroy
2016/05/12 12:15:14
nit - indent
oth
2016/05/12 14:59:53
Done.
| |
| 92 /* 0 30 E> */ B(StackCheck), | |
| 93 /* 1 42 S> */ B(LdaConstant), U8(0), | |
| 94 /* 3 42 E> */ B(Star), R8(1), | |
| 95 /* 5 68 S> */ B(JumpIfUndefined), U8(38), | |
| 96 /* 7 */ B(JumpIfNull), U8(36), | |
| 97 /* 9 */ B(ToObject), | |
| 98 /* 10 */ B(Star), R8(3), | |
| 99 /* 12 */ B(ForInPrepare), R8(4), | |
| 100 /* 14 */ B(LdaZero), | |
| 101 /* 15 */ B(Star), R8(7), | |
| 102 /* 17 63 S> */ B(ForInDone), R8(7), R8(6), | |
| 103 /* 20 */ B(JumpIfTrue), U8(23), | |
| 104 /* 22 */ B(ForInNext), R8(3), R8(7), R8(4), U8(1), | |
| 105 /* 27 */ B(JumpIfUndefined), U8(10), | |
| 106 /* 29 */ B(Star), R8(0), | |
| 107 /* 31 54 E> */ B(StackCheck), | |
| 108 /* 32 */ B(Ldar), R8(0), | |
| 109 /* 34 */ B(Star), R8(2), | |
| 110 /* 36 85 S> */ B(Return), | |
| 111 /* 37 */ B(ForInStep), R8(7), | |
| 112 /* 39 */ B(Star), R8(7), | |
| 113 /* 41 */ B(Jump), U8(-24), | |
| 114 /* 43 */ B(LdaUndefined), | |
| 115 /* 44 85 S> */ B(Return), | |
| 116 // clang-format on | |
|
rmcilroy
2016/05/12 12:15:14
nit - indent
oth
2016/05/12 14:59:53
Done.
| |
| 117 }; | |
| 118 | |
| 119 static const PositionTableEntry expected_positions[] = { | |
| 120 {0, 30, false}, {1, 42, true}, {3, 42, false}, {5, 68, true}, | |
| 121 {17, 63, true}, {31, 54, false}, {36, 85, true}, {44, 85, true}}; | |
| 122 | |
| 123 #define NODE(node_args) \ | |
|
rmcilroy
2016/05/12 12:15:14
Nit - these could be helper functions instead of m
oth
2016/05/12 14:59:53
Done.
| |
| 124 { \ | |
| 125 BytecodeNode node node_args; \ | |
| 126 writer()->Write(&node); \ | |
| 127 } | |
| 128 | |
| 129 #define NODE_SP(node_args, source_position, statement) \ | |
| 130 { \ | |
| 131 BytecodeNode node node_args; \ | |
| 132 node.source_info().Update({source_position, statement}); \ | |
| 133 writer()->Write(&node); \ | |
| 134 } | |
| 135 | |
| 136 #define R(i) static_cast<uint32_t>(Register(i).ToOperand()) | |
| 137 | |
| 138 NODE_SP((Bytecode::kStackCheck), 30, false); | |
| 139 NODE_SP((Bytecode::kLdaConstant, U8(0), OperandScale::kSingle), 42, true); | |
| 140 CHECK_EQ(writer()->GetMeasuredFrameSize(), 0 * kPointerSize); | |
| 141 NODE_SP((Bytecode::kStar, R(1), OperandScale::kSingle), 42, false); | |
| 142 CHECK_EQ(writer()->GetMeasuredFrameSize(), 2 * kPointerSize); | |
| 143 NODE_SP((Bytecode::kJumpIfUndefined, U8(38), OperandScale::kSingle), 68, | |
| 144 true); | |
| 145 NODE((Bytecode::kJumpIfNull, U8(36), OperandScale::kSingle)); | |
| 146 NODE((Bytecode::kToObject)); | |
| 147 CHECK_EQ(writer()->GetMeasuredFrameSize(), 2 * kPointerSize); | |
| 148 NODE((Bytecode::kStar, R(3), OperandScale::kSingle)); | |
| 149 CHECK_EQ(writer()->GetMeasuredFrameSize(), 4 * kPointerSize); | |
| 150 NODE((Bytecode::kForInPrepare, R(4), OperandScale::kSingle)); | |
| 151 CHECK_EQ(writer()->GetMeasuredFrameSize(), 7 * kPointerSize); | |
| 152 NODE((Bytecode::kLdaZero)); | |
| 153 CHECK_EQ(writer()->GetMeasuredFrameSize(), 7 * kPointerSize); | |
| 154 NODE((Bytecode::kStar, R(7), OperandScale::kSingle)); | |
| 155 CHECK_EQ(writer()->GetMeasuredFrameSize(), 8 * kPointerSize); | |
| 156 NODE_SP((Bytecode::kForInDone, R(7), R(6), OperandScale::kSingle), 63, true); | |
| 157 CHECK_EQ(writer()->GetMeasuredFrameSize(), 8 * kPointerSize); | |
| 158 NODE((Bytecode::kJumpIfTrue, U8(23), OperandScale::kSingle)); | |
| 159 NODE((Bytecode::kForInNext, R(3), R(7), R(4), U8(1), OperandScale::kSingle)); | |
| 160 NODE((Bytecode::kJumpIfUndefined, U8(10), OperandScale::kSingle)); | |
| 161 NODE((Bytecode::kStar, R(0), OperandScale::kSingle)); | |
| 162 NODE_SP((Bytecode::kStackCheck), 54, false); | |
| 163 NODE((Bytecode::kLdar, R(0), OperandScale::kSingle)); | |
| 164 NODE((Bytecode::kStar, R(2), OperandScale::kSingle)); | |
| 165 NODE_SP((Bytecode::kReturn), 85, true); | |
| 166 NODE((Bytecode::kForInStep, R(7), OperandScale::kSingle)); | |
| 167 NODE((Bytecode::kStar, R(7), OperandScale::kSingle)); | |
| 168 NODE((Bytecode::kJump, U8(-24), OperandScale::kSingle)); | |
| 169 NODE((Bytecode::kLdaUndefined)); | |
| 170 NODE_SP((Bytecode::kReturn), 85, true); | |
| 171 CHECK_EQ(writer()->GetMeasuredFrameSize(), 8 * kPointerSize); | |
| 172 | |
| 173 #undef NODE | |
| 174 #undef NODE_SP | |
| 175 #undef R | |
| 176 | |
| 177 CHECK_EQ(writer()->bytecodes()->size(), arraysize(expected_bytes)); | |
| 178 for (size_t i = 0; i < arraysize(expected_bytes); ++i) { | |
| 179 CHECK_EQ(static_cast<int>(writer()->bytecodes()->at(i)), | |
| 180 static_cast<int>(expected_bytes[i])); | |
| 181 } | |
| 182 | |
| 183 Handle<ByteArray> source_positions = | |
| 184 source_position_builder()->ToSourcePositionTable(); | |
| 185 SourcePositionTableIterator source_iterator(*source_positions); | |
| 186 for (size_t i = 0; i < arraysize(expected_positions); ++i) { | |
| 187 const PositionTableEntry& expected = expected_positions[i]; | |
| 188 CHECK_EQ(source_iterator.bytecode_offset(), expected.bytecode_offset); | |
| 189 CHECK_EQ(source_iterator.source_position(), expected.source_position); | |
| 190 CHECK_EQ(source_iterator.is_statement(), expected.is_statement); | |
| 191 source_iterator.Advance(); | |
| 192 } | |
| 193 CHECK(source_iterator.done()); | |
| 194 } | |
| 195 | |
| 196 } // namespace interpreter | |
| 197 } // namespace internal | |
| 198 } // namespace v8 | |
| OLD | NEW |