OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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/interpreter/bytecode-pipeline.h" | |
6 | |
7 #include <iomanip> | |
8 #include "src/interpreter/source-position-table.h" | |
9 | |
10 namespace v8 { | |
11 namespace internal { | |
12 namespace interpreter { | |
13 | |
14 void BytecodeSourceInfo::Update(const BytecodeSourceInfo& entry) { | |
15 DCHECK(entry.is_valid()); | |
16 if (!is_valid() || (entry.is_statement() && !is_statement()) || | |
17 (entry.is_statement() && is_statement() && | |
18 entry.source_position() > source_position())) { | |
19 // Position is updated if there is no existing position. Or the | |
20 // incoming position is a statement and the current position is an | |
21 // expression. Or we already have a statement and incoming | |
22 // statement is later. This last piece is needed for the first | |
23 // statement in a function. | |
24 source_position_ = entry.source_position_; | |
25 is_statement_ = entry.is_statement_; | |
26 } | |
27 } | |
28 | |
29 BytecodeNode::BytecodeNode(BytecodeNodeAllocator* allocator) | |
30 : bytecode_(Bytecode::kIllegal), | |
31 operand_scale_(OperandScale::kSingle), | |
32 allocator_(allocator) {} | |
33 | |
34 void BytecodeNode::set_bytecode(Bytecode bytecode) { | |
35 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); | |
36 bytecode_ = bytecode; | |
37 operand_scale_ = OperandScale::kSingle; | |
38 } | |
39 | |
40 void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0, | |
41 OperandScale operand_scale) { | |
42 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1); | |
43 bytecode_ = bytecode; | |
44 operands_[0] = operand0; | |
45 operand_scale_ = operand_scale; | |
46 } | |
47 | |
48 void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0, | |
49 uint32_t operand1, OperandScale operand_scale) { | |
50 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2); | |
51 bytecode_ = bytecode; | |
52 operands_[0] = operand0; | |
53 operands_[1] = operand1; | |
54 operand_scale_ = operand_scale; | |
55 } | |
56 | |
57 void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0, | |
58 uint32_t operand1, uint32_t operand2, | |
59 OperandScale operand_scale) { | |
60 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3); | |
61 bytecode_ = bytecode; | |
62 operands_[0] = operand0; | |
63 operands_[1] = operand1; | |
64 operands_[2] = operand2; | |
65 operand_scale_ = operand_scale; | |
66 } | |
67 | |
68 void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0, | |
69 uint32_t operand1, uint32_t operand2, | |
70 uint32_t operand3, OperandScale operand_scale) { | |
71 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 4); | |
72 bytecode_ = bytecode; | |
73 operands_[0] = operand0; | |
74 operands_[1] = operand1; | |
75 operands_[2] = operand2; | |
76 operands_[3] = operand3; | |
77 operand_scale_ = operand_scale; | |
78 } | |
79 | |
80 void BytecodeNode::replace_bytecode(Bytecode bytecode) { | |
81 if (bytecode == Bytecode::kNop) { | |
82 bytecode_ = bytecode; | |
83 operand_scale_ = OperandScale::kSingle; | |
84 return; | |
85 } | |
86 | |
87 if (Bytecodes::IsJump(bytecode) && Bytecodes::IsJump(bytecode_) && | |
88 Bytecodes::GetOperandType(bytecode, 0) == | |
89 Bytecodes::GetOperandType(bytecode_, 0)) { | |
rmcilroy
2016/05/10 11:14:10
I think we should only do these checks as DCHECKS
oth
2016/05/11 13:17:31
The semantics of CanReplace will be too cryptic aw
rmcilroy
2016/05/12 12:15:13
Works for me.
| |
90 bytecode_ = bytecode; | |
91 return; | |
92 } | |
93 | |
94 UNREACHABLE(); | |
95 } | |
96 | |
97 size_t BytecodeNode::Size() const { | |
98 size_t size = Bytecodes::Size(bytecode_, operand_scale_); | |
99 if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_)) { | |
100 size += 1; | |
101 } | |
102 return size; | |
103 } | |
104 | |
105 void BytecodeNode::Release() { | |
106 bytecode_ = Bytecode::kIllegal; | |
107 source_info_.set_invalid(); | |
108 allocator_->Release(this); | |
109 } | |
110 | |
111 void BytecodeNode::Print(std::ostream& os) { | |
112 #ifdef DEBUG | |
113 std::ios saved_state(nullptr); | |
114 saved_state.copyfmt(os); | |
115 | |
116 os << Bytecodes::ToString(bytecode_); | |
117 if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_)) { | |
118 Bytecode scale_prefix = | |
119 Bytecodes::OperandScaleToPrefixBytecode(operand_scale_); | |
120 os << '.' << Bytecodes::ToString(scale_prefix); | |
121 } | |
122 | |
123 for (int i = 0; i < operand_count(); ++i) { | |
124 os << ' ' << std::setw(8) << std::setfill('0') << std::hex << operands_[i]; | |
125 } | |
126 os.copyfmt(saved_state); | |
127 | |
128 if (source_info_.is_valid()) { | |
129 char type = source_info_.is_statement() ? 'S' : 'E'; | |
130 os << ' ' << type << '@' << source_info_.source_position(); | |
131 } | |
132 os << '\n'; | |
133 #endif // DEBUG | |
134 } | |
135 | |
136 BytecodeNode* BytecodeNodeAllocator::Allocate() { | |
137 if (free_list_ != nullptr) { | |
138 BytecodeNode* node = free_list_; | |
139 free_list_ = free_list_->next_; | |
140 return node; | |
141 } else { | |
142 DCHECK_LT(allocation_count_, kMaxDebugAllocations); | |
143 allocation_count_++; | |
144 return new (zone()) BytecodeNode(this); | |
145 } | |
146 } | |
147 | |
148 void BytecodeNodeAllocator::Release(BytecodeNode* node) { | |
149 node->next_ = free_list_; | |
150 free_list_ = node; | |
151 } | |
152 | |
153 } // namespace interpreter | |
154 } // namespace internal | |
155 } // namespace v8 | |
OLD | NEW |