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-array-builder.h" | |
6 | |
7 namespace v8 { | |
8 namespace internal { | |
9 namespace interpreter { | |
10 | |
11 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate) | |
12 : isolate_(isolate), | |
13 bytecode_generated_(false), | |
14 local_register_count_(-1), | |
15 temporary_register_count_(0), | |
16 temporary_register_next_(0) {} | |
17 | |
18 | |
19 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { | |
20 local_register_count_ = number_of_locals; | |
21 temporary_register_next_ = local_register_count_; | |
22 } | |
23 | |
24 | |
25 int BytecodeArrayBuilder::locals_count() const { return local_register_count_; } | |
26 | |
27 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { | |
28 DCHECK_EQ(bytecode_generated_, false); | |
29 DCHECK_GE(local_register_count_, 0); | |
30 int bytecode_size = static_cast<int>(bytecodes_.size()); | |
31 int register_count = local_register_count_ + temporary_register_count_; | |
32 int frame_size = register_count * kPointerSize; | |
33 Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray( | |
34 bytecode_size, &bytecodes_.front(), frame_size); | |
35 bytecode_generated_ = true; | |
36 return output; | |
37 } | |
38 | |
39 | |
40 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value binop, | |
41 int reg) { | |
42 Output(BytecodeForBinaryOperation(binop), reg); | |
43 return *this; | |
44 } | |
45 | |
46 | |
47 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( | |
48 v8::internal::Smi* smi) { | |
49 int32_t raw_smi = smi->value(); | |
50 if (raw_smi == 0) { | |
51 Output(Bytecode::kLdaZero); | |
52 } else if (raw_smi > -128 && raw_smi <= 128) { | |
53 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); | |
54 } else { | |
55 // TODO(oth): Put Smi in constant pool. | |
56 UNIMPLEMENTED(); | |
57 } | |
58 return *this; | |
59 } | |
60 | |
61 | |
62 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { | |
63 Output(Bytecode::kLdaUndefined); | |
64 return *this; | |
65 } | |
66 | |
67 | |
68 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() { | |
69 Output(Bytecode::kLdaNull); | |
70 return *this; | |
71 } | |
72 | |
73 | |
74 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() { | |
75 Output(Bytecode::kLdaTheHole); | |
76 return *this; | |
77 } | |
78 | |
79 | |
80 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() { | |
81 Output(Bytecode::kLdaTrue); | |
82 return *this; | |
83 } | |
84 | |
85 | |
86 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { | |
87 Output(Bytecode::kLdaFalse); | |
88 return *this; | |
89 } | |
90 | |
91 | |
92 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( | |
93 int reg) { | |
94 Output(Bytecode::kLdar, reg); | |
95 return *this; | |
96 } | |
97 | |
98 | |
99 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( | |
100 int reg) { | |
101 Output(Bytecode::kStar, reg); | |
102 return *this; | |
103 } | |
104 | |
105 | |
106 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { | |
107 Output(Bytecode::kReturn); | |
108 return *this; | |
109 } | |
110 | |
111 | |
112 int BytecodeArrayBuilder::BorrowTemporaryRegister() { | |
113 DCHECK_GE(local_register_count_, 0); | |
114 int temporary_register = temporary_register_next_++; | |
115 int count = temporary_register_next_ - local_register_count_; | |
116 if (count > temporary_register_count_) { | |
117 temporary_register_count_ = count; | |
118 } | |
119 return temporary_register; | |
120 } | |
121 | |
122 | |
123 void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg) { | |
124 DCHECK_EQ(reg, temporary_register_next_ - 1); | |
125 temporary_register_next_ = reg; | |
126 } | |
127 | |
128 | |
129 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, | |
130 uint8_t operand_value) const { | |
131 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); | |
132 switch (operand_type) { | |
133 case OperandType::kNone: | |
134 return false; | |
135 case OperandType::kImm8: | |
136 return true; | |
137 case OperandType::kReg: | |
138 return operand_value < temporary_register_next_; | |
139 } | |
140 UNREACHABLE(); | |
141 return false; | |
142 } | |
143 | |
144 | |
145 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0, | |
146 uint8_t operand1, uint8_t operand2) { | |
147 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3); | |
picksi
2015/08/03 11:06:01
This function does a DCHECK_EQ, the following func
oth
2015/08/03 15:39:59
Fixed, thanks!
| |
148 DCHECK(OperandIsValid(bytecode, 0, operand0) && | |
149 OperandIsValid(bytecode, 1, operand1) && | |
150 OperandIsValid(bytecode, 2, operand2)); | |
151 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
152 bytecodes_.push_back(operand0); | |
153 bytecodes_.push_back(operand1); | |
154 bytecodes_.push_back(operand2); | |
155 } | |
156 | |
157 | |
158 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0, | |
159 uint8_t operand1) { | |
160 DCHECK(Bytecodes::NumberOfOperands(bytecode) == 2); | |
161 DCHECK(OperandIsValid(bytecode, 0, operand0) && | |
162 OperandIsValid(bytecode, 1, operand1)); | |
163 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
164 bytecodes_.push_back(operand0); | |
165 bytecodes_.push_back(operand1); | |
166 } | |
167 | |
168 | |
169 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint8_t operand0) { | |
170 DCHECK(Bytecodes::NumberOfOperands(bytecode) == 1); | |
171 DCHECK(OperandIsValid(bytecode, 0, operand0)); | |
172 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
173 bytecodes_.push_back(operand0); | |
174 } | |
175 | |
176 | |
177 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | |
178 DCHECK(Bytecodes::NumberOfOperands(bytecode) == 0); | |
179 bytecodes_.push_back(Bytecodes::ToByte(bytecode)); | |
180 } | |
181 | |
182 | |
183 // static | |
184 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { | |
185 switch (op) { | |
186 case Token::Value::ADD: | |
187 return Bytecode::kAdd; | |
188 case Token::Value::SUB: | |
189 return Bytecode::kSub; | |
190 case Token::Value::MUL: | |
191 return Bytecode::kMul; | |
192 case Token::Value::DIV: | |
193 return Bytecode::kDiv; | |
194 default: | |
195 UNIMPLEMENTED(); | |
196 return static_cast<Bytecode>(-1); | |
picksi
2015/08/03 11:06:01
Should we have an error ByteCode that is -1, inste
oth
2015/08/03 15:39:59
In this instance, it's not recoverable error. The
| |
197 } | |
198 } | |
199 | |
200 | |
201 TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) | |
202 : builder_(builder), count_(0), register_(-1) {} | |
203 | |
204 | |
205 TemporaryRegisterScope::~TemporaryRegisterScope() { | |
206 while (count_-- != 0) { | |
207 builder_->ReturnTemporaryRegister(register_--); | |
208 } | |
209 } | |
210 | |
211 | |
212 int TemporaryRegisterScope::NewRegister() { | |
213 count_++; | |
214 register_ = builder_->BorrowTemporaryRegister(); | |
215 return register_; | |
216 } | |
217 | |
218 } // namespace interpreter | |
219 } // namespace internal | |
220 } // namespace v8 | |
OLD | NEW |