OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecode-array-builder.h" | 5 #include "src/interpreter/bytecode-array-builder.h" |
6 | 6 |
7 #include "src/globals.h" | 7 #include "src/globals.h" |
8 #include "src/interpreter/bytecode-array-writer.h" | 8 #include "src/interpreter/bytecode-array-writer.h" |
9 #include "src/interpreter/bytecode-dead-code-optimizer.h" | 9 #include "src/interpreter/bytecode-dead-code-optimizer.h" |
10 #include "src/interpreter/bytecode-label.h" | 10 #include "src/interpreter/bytecode-label.h" |
(...skipping 13 matching lines...) Expand all Loading... | |
24 bytecode_generated_(false), | 24 bytecode_generated_(false), |
25 constant_array_builder_(zone, isolate->factory()->the_hole_value()), | 25 constant_array_builder_(zone, isolate->factory()->the_hole_value()), |
26 handler_table_builder_(zone), | 26 handler_table_builder_(zone), |
27 return_seen_in_block_(false), | 27 return_seen_in_block_(false), |
28 parameter_count_(parameter_count), | 28 parameter_count_(parameter_count), |
29 local_register_count_(locals_count), | 29 local_register_count_(locals_count), |
30 context_register_count_(context_count), | 30 context_register_count_(context_count), |
31 register_allocator_(fixed_register_count()), | 31 register_allocator_(fixed_register_count()), |
32 bytecode_array_writer_(zone, &constant_array_builder_, | 32 bytecode_array_writer_(zone, &constant_array_builder_, |
33 source_position_mode), | 33 source_position_mode), |
34 pipeline_(&bytecode_array_writer_) { | 34 pipeline_(&bytecode_array_writer_), |
35 register_optimizer_(nullptr) { | |
35 DCHECK_GE(parameter_count_, 0); | 36 DCHECK_GE(parameter_count_, 0); |
36 DCHECK_GE(context_register_count_, 0); | 37 DCHECK_GE(context_register_count_, 0); |
37 DCHECK_GE(local_register_count_, 0); | 38 DCHECK_GE(local_register_count_, 0); |
38 | 39 |
39 if (FLAG_ignition_deadcode) { | 40 if (FLAG_ignition_deadcode) { |
40 pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_); | 41 pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_); |
41 } | 42 } |
42 | 43 |
43 if (FLAG_ignition_peephole) { | 44 if (FLAG_ignition_peephole) { |
44 pipeline_ = new (zone) BytecodePeepholeOptimizer(pipeline_); | 45 pipeline_ = new (zone) BytecodePeepholeOptimizer(pipeline_); |
45 } | 46 } |
46 | 47 |
47 if (FLAG_ignition_reo) { | 48 if (FLAG_ignition_reo) { |
48 pipeline_ = new (zone) BytecodeRegisterOptimizer( | 49 register_optimizer_ = new (zone) BytecodeRegisterOptimizer( |
49 zone, ®ister_allocator_, fixed_register_count(), parameter_count, | 50 zone, ®ister_allocator_, fixed_register_count(), parameter_count, |
50 pipeline_); | 51 pipeline_); |
Leszek Swirski
2016/10/07 08:34:10
I don't love that both this class and the register
rmcilroy
2016/10/24 16:27:55
As discussed offline, this isn't super easy. Let's
| |
51 } | 52 } |
52 | 53 |
53 return_position_ = | 54 return_position_ = |
54 literal ? std::max(literal->start_position(), literal->end_position() - 1) | 55 literal ? std::max(literal->start_position(), literal->end_position() - 1) |
55 : kNoSourcePosition; | 56 : kNoSourcePosition; |
56 } | 57 } |
57 | 58 |
58 Register BytecodeArrayBuilder::first_context_register() const { | 59 Register BytecodeArrayBuilder::first_context_register() const { |
59 DCHECK_GT(context_register_count_, 0); | 60 DCHECK_GT(context_register_count_, 0); |
60 return Register(local_register_count_); | 61 return Register(local_register_count_); |
61 } | 62 } |
62 | 63 |
63 Register BytecodeArrayBuilder::last_context_register() const { | 64 Register BytecodeArrayBuilder::last_context_register() const { |
64 DCHECK_GT(context_register_count_, 0); | 65 DCHECK_GT(context_register_count_, 0); |
65 return Register(local_register_count_ + context_register_count_ - 1); | 66 return Register(local_register_count_ + context_register_count_ - 1); |
66 } | 67 } |
67 | 68 |
68 Register BytecodeArrayBuilder::Parameter(int parameter_index) const { | 69 Register BytecodeArrayBuilder::Parameter(int parameter_index) const { |
69 DCHECK_GE(parameter_index, 0); | 70 DCHECK_GE(parameter_index, 0); |
70 return Register::FromParameterIndex(parameter_index, parameter_count()); | 71 return Register::FromParameterIndex(parameter_index, parameter_count()); |
71 } | 72 } |
72 | 73 |
73 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { | 74 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { |
74 DCHECK(return_seen_in_block_); | 75 DCHECK(return_seen_in_block_); |
75 DCHECK(!bytecode_generated_); | 76 DCHECK(!bytecode_generated_); |
76 bytecode_generated_ = true; | 77 bytecode_generated_ = true; |
77 | 78 |
79 int register_count = total_register_count(); | |
80 | |
81 if (register_optimizer_) { | |
82 register_optimizer_->Flush(); | |
83 register_count = register_optimizer_->maxiumum_register_index() + 1; | |
84 } | |
85 | |
78 Handle<FixedArray> handler_table = | 86 Handle<FixedArray> handler_table = |
79 handler_table_builder()->ToHandlerTable(isolate); | 87 handler_table_builder()->ToHandlerTable(isolate); |
80 return pipeline_->ToBytecodeArray(isolate, total_register_count(), | 88 return pipeline_->ToBytecodeArray(isolate, register_count, parameter_count(), |
81 parameter_count(), handler_table); | 89 handler_table); |
82 } | 90 } |
83 | 91 |
84 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 92 BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition( |
85 uint32_t operand1, uint32_t operand2, | 93 Bytecode bytecode) { |
86 uint32_t operand3) { | 94 BytecodeSourceInfo source_position; |
87 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); | 95 if (latest_source_info_.is_valid()) { |
88 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, | 96 // Statement positions need to be emitted immediately. Expression |
89 &latest_source_info_); | 97 // positions can be pushed back until a bytecode is found that can |
90 pipeline()->Write(&node); | 98 // throw (if expression position filtering is turned on). We only |
99 // invalidate the existing source position information if it is used. | |
100 if (latest_source_info_.is_statement() || | |
101 !FLAG_ignition_filter_expression_positions || | |
102 !Bytecodes::IsWithoutExternalSideEffects(bytecode)) { | |
Leszek Swirski
2016/10/06 10:35:17
not sure what effect this would have on execution
rmcilroy
2016/10/06 17:14:43
Yeah, I made IsWithoutExternalSideEffects a conste
Leszek Swirski
2016/10/07 08:34:10
Oh yeah, inlining, stupid me. Did you check if it
rmcilroy
2016/10/24 16:27:55
Yeah it is, at least for the functions which appea
| |
103 source_position.Clone(latest_source_info_); | |
104 latest_source_info_.set_invalid(); | |
Leszek Swirski
2016/10/06 10:35:17
maybe not for this CL, but this could be done a bi
rmcilroy
2016/10/06 17:14:43
This caused a bunch of issues elsewhere with the d
Leszek Swirski
2016/10/07 08:34:10
Fair enough, I might put that refactor on my backl
| |
105 } | |
106 } | |
107 return source_position; | |
91 } | 108 } |
92 | 109 |
93 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 110 namespace { |
94 uint32_t operand1, uint32_t operand2) { | 111 |
95 DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2)); | 112 template <OperandTypeInfo type_info> |
96 BytecodeNode node(bytecode, operand0, operand1, operand2, | 113 class UnsignedOperandHelper { |
97 &latest_source_info_); | 114 public: |
98 pipeline()->Write(&node); | 115 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, size_t value)) { |
99 } | 116 DCHECK(IsValid(value)); |
100 | 117 return static_cast<uint32_t>(value); |
101 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 118 } |
102 uint32_t operand1) { | 119 |
103 DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1)); | 120 static uint32_t Convert(BytecodeArrayBuilder* builder, int value) { |
Leszek Swirski
2016/10/06 10:35:17
why not INLINE?
rmcilroy
2016/10/06 17:14:43
Done.
| |
104 BytecodeNode node(bytecode, operand0, operand1, &latest_source_info_); | 121 DCHECK_GE(value, 0); |
105 pipeline()->Write(&node); | 122 return Convert(builder, static_cast<size_t>(value)); |
106 } | 123 } |
107 | 124 |
108 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { | 125 static bool IsValid(size_t value) { |
Leszek Swirski
2016/10/06 10:35:17
maybe private?
rmcilroy
2016/10/06 17:14:43
Done.
| |
109 DCHECK(OperandsAreValid(bytecode, 1, operand0)); | 126 switch (type_info) { |
110 BytecodeNode node(bytecode, operand0, &latest_source_info_); | 127 case OperandTypeInfo::kFixedUnsignedByte: |
111 pipeline()->Write(&node); | 128 return value <= kMaxUInt8; |
112 } | 129 case OperandTypeInfo::kFixedUnsignedShort: |
113 | 130 return value <= kMaxUInt16; |
114 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 131 case OperandTypeInfo::kScalableUnsignedByte: |
115 DCHECK(OperandsAreValid(bytecode, 0)); | 132 return value <= kMaxUInt32; |
116 BytecodeNode node(bytecode, &latest_source_info_); | 133 default: |
117 pipeline()->Write(&node); | 134 UNREACHABLE(); |
118 } | 135 return false; |
119 | 136 } |
120 void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, BytecodeLabel* label) { | 137 } |
121 BytecodeNode node(bytecode, 0, &latest_source_info_); | 138 }; |
122 pipeline_->WriteJump(&node, label); | 139 |
123 LeaveBasicBlock(); | 140 template <OperandType> |
124 } | 141 class OperandHelper {}; |
125 | 142 |
126 void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, uint32_t operand0, | 143 #define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \ |
127 BytecodeLabel* label) { | 144 template <> \ |
128 BytecodeNode node(bytecode, 0, operand0, &latest_source_info_); | 145 class OperandHelper<OperandType::k##Name> \ |
129 pipeline_->WriteJump(&node, label); | 146 : public UnsignedOperandHelper<Type> {}; |
130 LeaveBasicBlock(); | 147 UNSIGNED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER) |
131 } | 148 #undef DEFINE_UNSIGNED_OPERAND_HELPER |
149 | |
150 template <> | |
151 class OperandHelper<OperandType::kImm> { | |
152 public: | |
153 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) { | |
154 return static_cast<uint32_t>(value); | |
155 } | |
156 }; | |
157 | |
158 template <> | |
159 class OperandHelper<OperandType::kReg> { | |
160 public: | |
161 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) { | |
162 return builder->GetInputRegisterOperand(reg); | |
163 } | |
164 }; | |
165 | |
166 template <> | |
167 class OperandHelper<OperandType::kRegList> { | |
168 public: | |
169 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, | |
170 RegisterList reg_list)) { | |
171 return builder->GetInputRegisterListOperand(reg_list); | |
172 } | |
173 }; | |
174 | |
175 template <> | |
176 class OperandHelper<OperandType::kRegPair> { | |
177 public: | |
178 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, | |
179 RegisterList reg_list)) { | |
180 DCHECK_EQ(reg_list.register_count(), 2); | |
181 return builder->GetInputRegisterListOperand(reg_list); | |
182 } | |
183 }; | |
184 | |
185 template <> | |
186 class OperandHelper<OperandType::kRegOut> { | |
187 public: | |
188 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) { | |
189 return builder->GetOutputRegisterOperand(reg); | |
190 } | |
191 }; | |
192 | |
193 template <> | |
194 class OperandHelper<OperandType::kRegOutPair> { | |
195 public: | |
196 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, | |
197 RegisterList reg_list)) { | |
198 DCHECK_EQ(2, reg_list.register_count()); | |
199 return builder->GetOutputRegisterListOperand(reg_list); | |
200 } | |
201 }; | |
202 | |
203 template <> | |
204 class OperandHelper<OperandType::kRegOutTriple> { | |
205 public: | |
206 INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, | |
207 RegisterList reg_list)) { | |
208 DCHECK_EQ(3, reg_list.register_count()); | |
209 return builder->GetOutputRegisterListOperand(reg_list); | |
210 } | |
211 }; | |
212 | |
213 template <OperandType... operand_types> | |
214 class BytecodeNodeBuilder { | |
215 public: | |
216 template <typename... Operands> | |
217 INLINE(static BytecodeNode Make(Bytecode bytecode, Operands... operands, | |
218 BytecodeSourceInfo source_info, | |
219 BytecodeArrayBuilder* builder)) { | |
220 builder->PrepareToOutputBytecode(bytecode); | |
221 return BytecodeNode( | |
222 bytecode, OperandHelper<operand_types>::Convert(builder, operands)..., | |
Leszek Swirski
2016/10/06 10:35:17
It might be helpful for future readers of this cod
rmcilroy
2016/10/06 17:14:43
Done.
| |
223 source_info); | |
224 } | |
225 }; | |
226 | |
227 } // namespace | |
228 | |
229 #define DEFINE_BYTECODE_OUTPUT(name, accumulator_use, ...) \ | |
230 template <typename... Operands> \ | |
231 void BytecodeArrayBuilder::Output##name(Operands... operands) { \ | |
232 BytecodeNode node(BytecodeNodeBuilder<__VA_ARGS__>::Make<Operands...>( \ | |
233 Bytecode::k##name, operands..., \ | |
234 CurrentSourcePosition(Bytecode::k##name), this)); \ | |
235 pipeline()->Write(&node); \ | |
236 } \ | |
237 \ | |
238 template <typename... Operands> \ | |
239 void BytecodeArrayBuilder::Output##name(BytecodeLabel* label, \ | |
240 Operands... operands) { \ | |
241 DCHECK(Bytecodes::IsJump(Bytecode::k##name)); \ | |
242 BytecodeNode node(BytecodeNodeBuilder<__VA_ARGS__>::Make<Operands...>( \ | |
243 Bytecode::k##name, operands..., \ | |
244 CurrentSourcePosition(Bytecode::k##name), this)); \ | |
245 pipeline()->WriteJump(&node, label); \ | |
246 LeaveBasicBlock(); \ | |
247 } | |
248 BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT) | |
249 #undef DEFINE_BYTECODE_OUTPUT | |
132 | 250 |
133 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 251 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
134 Register reg, | 252 Register reg, |
135 int feedback_slot) { | 253 int feedback_slot) { |
136 switch (op) { | 254 switch (op) { |
137 case Token::Value::ADD: | 255 case Token::Value::ADD: |
138 Output(Bytecode::kAdd, RegisterOperand(reg), | 256 OutputAdd(reg, feedback_slot); |
139 UnsignedOperand(feedback_slot)); | |
140 break; | 257 break; |
141 case Token::Value::SUB: | 258 case Token::Value::SUB: |
142 Output(Bytecode::kSub, RegisterOperand(reg), | 259 OutputSub(reg, feedback_slot); |
143 UnsignedOperand(feedback_slot)); | |
144 break; | 260 break; |
145 case Token::Value::MUL: | 261 case Token::Value::MUL: |
146 Output(Bytecode::kMul, RegisterOperand(reg), | 262 OutputMul(reg, feedback_slot); |
147 UnsignedOperand(feedback_slot)); | |
148 break; | 263 break; |
149 case Token::Value::DIV: | 264 case Token::Value::DIV: |
150 Output(Bytecode::kDiv, RegisterOperand(reg), | 265 OutputDiv(reg, feedback_slot); |
151 UnsignedOperand(feedback_slot)); | |
152 break; | 266 break; |
153 case Token::Value::MOD: | 267 case Token::Value::MOD: |
154 Output(Bytecode::kMod, RegisterOperand(reg), | 268 OutputMod(reg, feedback_slot); |
155 UnsignedOperand(feedback_slot)); | |
156 break; | 269 break; |
157 case Token::Value::BIT_OR: | 270 case Token::Value::BIT_OR: |
158 Output(Bytecode::kBitwiseOr, RegisterOperand(reg), | 271 OutputBitwiseOr(reg, feedback_slot); |
159 UnsignedOperand(feedback_slot)); | |
160 break; | 272 break; |
161 case Token::Value::BIT_XOR: | 273 case Token::Value::BIT_XOR: |
162 Output(Bytecode::kBitwiseXor, RegisterOperand(reg), | 274 OutputBitwiseXor(reg, feedback_slot); |
163 UnsignedOperand(feedback_slot)); | |
164 break; | 275 break; |
165 case Token::Value::BIT_AND: | 276 case Token::Value::BIT_AND: |
166 Output(Bytecode::kBitwiseAnd, RegisterOperand(reg), | 277 OutputBitwiseAnd(reg, feedback_slot); |
167 UnsignedOperand(feedback_slot)); | |
168 break; | 278 break; |
169 case Token::Value::SHL: | 279 case Token::Value::SHL: |
170 Output(Bytecode::kShiftLeft, RegisterOperand(reg), | 280 OutputShiftLeft(reg, feedback_slot); |
171 UnsignedOperand(feedback_slot)); | |
172 break; | 281 break; |
173 case Token::Value::SAR: | 282 case Token::Value::SAR: |
174 Output(Bytecode::kShiftRight, RegisterOperand(reg), | 283 OutputShiftRight(reg, feedback_slot); |
175 UnsignedOperand(feedback_slot)); | |
176 break; | 284 break; |
177 case Token::Value::SHR: | 285 case Token::Value::SHR: |
178 Output(Bytecode::kShiftRightLogical, RegisterOperand(reg), | 286 OutputShiftRightLogical(reg, feedback_slot); |
179 UnsignedOperand(feedback_slot)); | |
180 break; | 287 break; |
181 default: | 288 default: |
182 UNREACHABLE(); | 289 UNREACHABLE(); |
183 } | 290 } |
184 return *this; | 291 return *this; |
185 } | 292 } |
186 | 293 |
187 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, | 294 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, |
188 int feedback_slot) { | 295 int feedback_slot) { |
189 if (op == Token::Value::ADD) { | 296 if (op == Token::Value::ADD) { |
190 Output(Bytecode::kInc, UnsignedOperand(feedback_slot)); | 297 OutputInc(feedback_slot); |
191 } else { | 298 } else { |
192 DCHECK_EQ(op, Token::Value::SUB); | 299 DCHECK_EQ(op, Token::Value::SUB); |
193 Output(Bytecode::kDec, UnsignedOperand(feedback_slot)); | 300 OutputDec(feedback_slot); |
194 } | 301 } |
195 return *this; | 302 return *this; |
196 } | 303 } |
197 | 304 |
198 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { | 305 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { |
199 Output(Bytecode::kToBooleanLogicalNot); | 306 OutputToBooleanLogicalNot(); |
200 return *this; | 307 return *this; |
201 } | 308 } |
202 | 309 |
203 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { | 310 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { |
204 Output(Bytecode::kTypeOf); | 311 OutputTypeOf(); |
205 return *this; | 312 return *this; |
206 } | 313 } |
207 | 314 |
208 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( | 315 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( |
209 Token::Value op, Register reg, int feedback_slot) { | 316 Token::Value op, Register reg, int feedback_slot) { |
210 switch (op) { | 317 switch (op) { |
211 case Token::Value::EQ: | 318 case Token::Value::EQ: |
212 Output(Bytecode::kTestEqual, RegisterOperand(reg), | 319 OutputTestEqual(reg, feedback_slot); |
213 UnsignedOperand(feedback_slot)); | |
214 break; | 320 break; |
215 case Token::Value::NE: | 321 case Token::Value::NE: |
216 Output(Bytecode::kTestNotEqual, RegisterOperand(reg), | 322 OutputTestNotEqual(reg, feedback_slot); |
217 UnsignedOperand(feedback_slot)); | |
218 break; | 323 break; |
219 case Token::Value::EQ_STRICT: | 324 case Token::Value::EQ_STRICT: |
220 Output(Bytecode::kTestEqualStrict, RegisterOperand(reg), | 325 OutputTestEqualStrict(reg, feedback_slot); |
221 UnsignedOperand(feedback_slot)); | |
222 break; | 326 break; |
223 case Token::Value::LT: | 327 case Token::Value::LT: |
224 Output(Bytecode::kTestLessThan, RegisterOperand(reg), | 328 OutputTestLessThan(reg, feedback_slot); |
225 UnsignedOperand(feedback_slot)); | |
226 break; | 329 break; |
227 case Token::Value::GT: | 330 case Token::Value::GT: |
228 Output(Bytecode::kTestGreaterThan, RegisterOperand(reg), | 331 OutputTestGreaterThan(reg, feedback_slot); |
229 UnsignedOperand(feedback_slot)); | |
230 break; | 332 break; |
231 case Token::Value::LTE: | 333 case Token::Value::LTE: |
232 Output(Bytecode::kTestLessThanOrEqual, RegisterOperand(reg), | 334 OutputTestLessThanOrEqual(reg, feedback_slot); |
233 UnsignedOperand(feedback_slot)); | |
234 break; | 335 break; |
235 case Token::Value::GTE: | 336 case Token::Value::GTE: |
236 Output(Bytecode::kTestGreaterThanOrEqual, RegisterOperand(reg), | 337 OutputTestGreaterThanOrEqual(reg, feedback_slot); |
237 UnsignedOperand(feedback_slot)); | |
238 break; | 338 break; |
239 case Token::Value::INSTANCEOF: | 339 case Token::Value::INSTANCEOF: |
240 Output(Bytecode::kTestInstanceOf, RegisterOperand(reg)); | 340 OutputTestInstanceOf(reg); |
241 break; | 341 break; |
242 case Token::Value::IN: | 342 case Token::Value::IN: |
243 Output(Bytecode::kTestIn, RegisterOperand(reg)); | 343 OutputTestIn(reg); |
244 break; | 344 break; |
245 default: | 345 default: |
246 UNREACHABLE(); | 346 UNREACHABLE(); |
247 } | 347 } |
248 return *this; | 348 return *this; |
249 } | 349 } |
250 | 350 |
251 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( | 351 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( |
252 size_t entry) { | 352 size_t entry) { |
253 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); | 353 OutputLdaConstant(entry); |
254 return *this; | 354 return *this; |
255 } | 355 } |
256 | 356 |
257 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( | 357 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( |
258 v8::internal::Smi* smi) { | 358 v8::internal::Smi* smi) { |
259 int32_t raw_smi = smi->value(); | 359 int32_t raw_smi = smi->value(); |
260 if (raw_smi == 0) { | 360 if (raw_smi == 0) { |
261 Output(Bytecode::kLdaZero); | 361 OutputLdaZero(); |
262 } else { | 362 } else { |
263 Output(Bytecode::kLdaSmi, SignedOperand(raw_smi)); | 363 OutputLdaSmi(raw_smi); |
264 } | 364 } |
265 return *this; | 365 return *this; |
266 } | 366 } |
267 | 367 |
268 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { | 368 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { |
269 size_t entry = GetConstantPoolEntry(object); | 369 size_t entry = GetConstantPoolEntry(object); |
270 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); | 370 OutputLdaConstant(entry); |
271 return *this; | 371 return *this; |
272 } | 372 } |
273 | 373 |
274 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { | 374 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { |
275 Output(Bytecode::kLdaUndefined); | 375 OutputLdaUndefined(); |
276 return *this; | 376 return *this; |
277 } | 377 } |
278 | 378 |
279 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() { | 379 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() { |
280 Output(Bytecode::kLdaNull); | 380 OutputLdaNull(); |
281 return *this; | 381 return *this; |
282 } | 382 } |
283 | 383 |
284 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() { | 384 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() { |
285 Output(Bytecode::kLdaTheHole); | 385 OutputLdaTheHole(); |
286 return *this; | 386 return *this; |
287 } | 387 } |
288 | 388 |
289 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() { | 389 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() { |
290 Output(Bytecode::kLdaTrue); | 390 OutputLdaTrue(); |
291 return *this; | 391 return *this; |
292 } | 392 } |
293 | 393 |
294 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { | 394 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { |
295 Output(Bytecode::kLdaFalse); | 395 OutputLdaFalse(); |
296 return *this; | 396 return *this; |
297 } | 397 } |
298 | 398 |
299 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( | 399 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( |
300 Register reg) { | 400 Register reg) { |
301 Output(Bytecode::kLdar, RegisterOperand(reg)); | 401 if (register_optimizer_) { |
402 register_optimizer_->DoLdar(reg, CurrentSourcePosition(Bytecode::kLdar)); | |
403 } else { | |
404 OutputLdar(reg); | |
405 } | |
302 return *this; | 406 return *this; |
303 } | 407 } |
304 | 408 |
305 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( | 409 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
306 Register reg) { | 410 Register reg) { |
307 Output(Bytecode::kStar, RegisterOperand(reg)); | 411 if (register_optimizer_) { |
412 register_optimizer_->DoStar(reg, CurrentSourcePosition(Bytecode::kStar)); | |
413 } else { | |
414 OutputStar(reg); | |
415 } | |
308 return *this; | 416 return *this; |
309 } | 417 } |
310 | 418 |
311 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, | 419 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
312 Register to) { | 420 Register to) { |
313 DCHECK(from != to); | 421 DCHECK(from != to); |
314 Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to)); | 422 if (register_optimizer_) { |
423 register_optimizer_->DoMov(from, to, CurrentSourcePosition(Bytecode::kMov)); | |
424 } else { | |
425 OutputMov(from, to); | |
426 } | |
315 return *this; | 427 return *this; |
316 } | 428 } |
317 | 429 |
318 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, | 430 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, |
319 TypeofMode typeof_mode) { | 431 TypeofMode typeof_mode) { |
320 if (typeof_mode == INSIDE_TYPEOF) { | 432 if (typeof_mode == INSIDE_TYPEOF) { |
321 Output(Bytecode::kLdaGlobalInsideTypeof, feedback_slot); | 433 OutputLdaGlobalInsideTypeof(feedback_slot); |
322 } else { | 434 } else { |
323 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); | 435 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); |
324 Output(Bytecode::kLdaGlobal, UnsignedOperand(feedback_slot)); | 436 OutputLdaGlobal(feedback_slot); |
325 } | 437 } |
326 return *this; | 438 return *this; |
327 } | 439 } |
328 | 440 |
329 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( | 441 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( |
330 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { | 442 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { |
331 size_t name_index = GetConstantPoolEntry(name); | 443 size_t name_index = GetConstantPoolEntry(name); |
332 if (language_mode == SLOPPY) { | 444 if (language_mode == SLOPPY) { |
333 Output(Bytecode::kStaGlobalSloppy, UnsignedOperand(name_index), | 445 OutputStaGlobalSloppy(name_index, feedback_slot); |
334 UnsignedOperand(feedback_slot)); | |
335 } else { | 446 } else { |
336 DCHECK_EQ(language_mode, STRICT); | 447 DCHECK_EQ(language_mode, STRICT); |
337 Output(Bytecode::kStaGlobalStrict, UnsignedOperand(name_index), | 448 OutputStaGlobalStrict(name_index, feedback_slot); |
338 UnsignedOperand(feedback_slot)); | |
339 } | 449 } |
340 return *this; | 450 return *this; |
341 } | 451 } |
342 | 452 |
343 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, | 453 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
344 int slot_index, | 454 int slot_index, |
345 int depth) { | 455 int depth) { |
346 Output(Bytecode::kLdaContextSlot, RegisterOperand(context), | 456 OutputLdaContextSlot(context, slot_index, depth); |
347 UnsignedOperand(slot_index), UnsignedOperand(depth)); | |
348 return *this; | 457 return *this; |
349 } | 458 } |
350 | 459 |
351 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, | 460 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, |
352 int slot_index, | 461 int slot_index, |
353 int depth) { | 462 int depth) { |
354 Output(Bytecode::kStaContextSlot, RegisterOperand(context), | 463 OutputStaContextSlot(context, slot_index, depth); |
355 UnsignedOperand(slot_index), UnsignedOperand(depth)); | |
356 return *this; | 464 return *this; |
357 } | 465 } |
358 | 466 |
359 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( | 467 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( |
360 const Handle<String> name, TypeofMode typeof_mode) { | 468 const Handle<String> name, TypeofMode typeof_mode) { |
361 size_t name_index = GetConstantPoolEntry(name); | 469 size_t name_index = GetConstantPoolEntry(name); |
362 if (typeof_mode == INSIDE_TYPEOF) { | 470 if (typeof_mode == INSIDE_TYPEOF) { |
363 Output(Bytecode::kLdaLookupSlotInsideTypeof, UnsignedOperand(name_index)); | 471 OutputLdaLookupSlotInsideTypeof(name_index); |
364 } else { | 472 } else { |
365 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); | 473 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); |
366 Output(Bytecode::kLdaLookupSlot, UnsignedOperand(name_index)); | 474 OutputLdaLookupSlot(name_index); |
367 } | 475 } |
368 return *this; | 476 return *this; |
369 } | 477 } |
370 | 478 |
371 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot( | 479 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot( |
372 const Handle<String> name, TypeofMode typeof_mode, int slot_index, | 480 const Handle<String> name, TypeofMode typeof_mode, int slot_index, |
373 int depth) { | 481 int depth) { |
374 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | |
375 ? Bytecode::kLdaLookupContextSlotInsideTypeof | |
376 : Bytecode::kLdaLookupContextSlot; | |
377 size_t name_index = GetConstantPoolEntry(name); | 482 size_t name_index = GetConstantPoolEntry(name); |
378 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(slot_index), | 483 if (typeof_mode == INSIDE_TYPEOF) { |
379 UnsignedOperand(depth)); | 484 OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth); |
485 } else { | |
486 DCHECK(typeof_mode == NOT_INSIDE_TYPEOF); | |
487 OutputLdaLookupContextSlot(name_index, slot_index, depth); | |
488 } | |
380 return *this; | 489 return *this; |
381 } | 490 } |
382 | 491 |
383 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot( | 492 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot( |
384 const Handle<String> name, TypeofMode typeof_mode, int feedback_slot, | 493 const Handle<String> name, TypeofMode typeof_mode, int feedback_slot, |
385 int depth) { | 494 int depth) { |
386 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | |
387 ? Bytecode::kLdaLookupGlobalSlotInsideTypeof | |
388 : Bytecode::kLdaLookupGlobalSlot; | |
389 size_t name_index = GetConstantPoolEntry(name); | 495 size_t name_index = GetConstantPoolEntry(name); |
390 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot), | 496 if (typeof_mode == INSIDE_TYPEOF) { |
391 UnsignedOperand(depth)); | 497 OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth); |
498 } else { | |
499 DCHECK(typeof_mode == NOT_INSIDE_TYPEOF); | |
500 OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth); | |
501 } | |
392 return *this; | 502 return *this; |
393 } | 503 } |
394 | 504 |
395 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( | 505 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( |
396 const Handle<String> name, LanguageMode language_mode) { | 506 const Handle<String> name, LanguageMode language_mode) { |
397 size_t name_index = GetConstantPoolEntry(name); | 507 size_t name_index = GetConstantPoolEntry(name); |
398 if (language_mode == SLOPPY) { | 508 if (language_mode == SLOPPY) { |
399 Output(Bytecode::kStaLookupSlotSloppy, UnsignedOperand(name_index)); | 509 OutputStaLookupSlotSloppy(name_index); |
400 } else { | 510 } else { |
401 DCHECK_EQ(language_mode, STRICT); | 511 DCHECK_EQ(language_mode, STRICT); |
402 Output(Bytecode::kStaLookupSlotStrict, UnsignedOperand(name_index)); | 512 OutputStaLookupSlotStrict(name_index); |
403 } | 513 } |
404 return *this; | 514 return *this; |
405 } | 515 } |
406 | 516 |
407 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 517 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
408 Register object, const Handle<Name> name, int feedback_slot) { | 518 Register object, const Handle<Name> name, int feedback_slot) { |
409 size_t name_index = GetConstantPoolEntry(name); | 519 size_t name_index = GetConstantPoolEntry(name); |
410 Output(Bytecode::kLdaNamedProperty, RegisterOperand(object), | 520 OutputLdaNamedProperty(object, name_index, feedback_slot); |
411 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | |
412 return *this; | 521 return *this; |
413 } | 522 } |
414 | 523 |
415 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 524 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
416 Register object, int feedback_slot) { | 525 Register object, int feedback_slot) { |
417 Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object), | 526 OutputLdaKeyedProperty(object, feedback_slot); |
418 UnsignedOperand(feedback_slot)); | |
419 return *this; | 527 return *this; |
420 } | 528 } |
421 | 529 |
422 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 530 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
423 Register object, const Handle<Name> name, int feedback_slot, | 531 Register object, const Handle<Name> name, int feedback_slot, |
424 LanguageMode language_mode) { | 532 LanguageMode language_mode) { |
425 size_t name_index = GetConstantPoolEntry(name); | 533 size_t name_index = GetConstantPoolEntry(name); |
426 if (language_mode == SLOPPY) { | 534 if (language_mode == SLOPPY) { |
427 Output(Bytecode::kStaNamedPropertySloppy, RegisterOperand(object), | 535 OutputStaNamedPropertySloppy(object, name_index, feedback_slot); |
428 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | |
429 } else { | 536 } else { |
430 DCHECK_EQ(language_mode, STRICT); | 537 DCHECK_EQ(language_mode, STRICT); |
431 Output(Bytecode::kStaNamedPropertyStrict, RegisterOperand(object), | 538 OutputStaNamedPropertyStrict(object, name_index, feedback_slot); |
432 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | |
433 } | 539 } |
434 return *this; | 540 return *this; |
435 } | 541 } |
436 | 542 |
437 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 543 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
438 Register object, Register key, int feedback_slot, | 544 Register object, Register key, int feedback_slot, |
439 LanguageMode language_mode) { | 545 LanguageMode language_mode) { |
440 if (language_mode == SLOPPY) { | 546 if (language_mode == SLOPPY) { |
441 Output(Bytecode::kStaKeyedPropertySloppy, RegisterOperand(object), | 547 OutputStaKeyedPropertySloppy(object, key, feedback_slot); |
442 RegisterOperand(key), UnsignedOperand(feedback_slot)); | |
443 } else { | 548 } else { |
444 DCHECK_EQ(language_mode, STRICT); | 549 DCHECK_EQ(language_mode, STRICT); |
445 Output(Bytecode::kStaKeyedPropertyStrict, RegisterOperand(object), | 550 OutputStaKeyedPropertyStrict(object, key, feedback_slot); |
446 RegisterOperand(key), UnsignedOperand(feedback_slot)); | |
447 } | 551 } |
448 return *this; | 552 return *this; |
449 } | 553 } |
450 | 554 |
451 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, | 555 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, |
452 int flags) { | 556 int flags) { |
453 Output(Bytecode::kCreateClosure, UnsignedOperand(entry), | 557 OutputCreateClosure(entry, flags); |
454 UnsignedOperand(flags)); | |
455 return *this; | 558 return *this; |
456 } | 559 } |
457 | 560 |
458 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext( | 561 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext( |
459 Handle<ScopeInfo> scope_info) { | 562 Handle<ScopeInfo> scope_info) { |
460 size_t entry = GetConstantPoolEntry(scope_info); | 563 size_t entry = GetConstantPoolEntry(scope_info); |
461 Output(Bytecode::kCreateBlockContext, UnsignedOperand(entry)); | 564 OutputCreateBlockContext(entry); |
462 return *this; | 565 return *this; |
463 } | 566 } |
464 | 567 |
465 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext( | 568 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext( |
466 Register exception, Handle<String> name, Handle<ScopeInfo> scope_info) { | 569 Register exception, Handle<String> name, Handle<ScopeInfo> scope_info) { |
467 size_t name_index = GetConstantPoolEntry(name); | 570 size_t name_index = GetConstantPoolEntry(name); |
468 size_t scope_info_index = GetConstantPoolEntry(scope_info); | 571 size_t scope_info_index = GetConstantPoolEntry(scope_info); |
469 Output(Bytecode::kCreateCatchContext, RegisterOperand(exception), | 572 OutputCreateCatchContext(exception, name_index, scope_info_index); |
470 UnsignedOperand(name_index), UnsignedOperand(scope_info_index)); | |
471 return *this; | 573 return *this; |
472 } | 574 } |
473 | 575 |
474 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) { | 576 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) { |
475 Output(Bytecode::kCreateFunctionContext, UnsignedOperand(slots)); | 577 OutputCreateFunctionContext(slots); |
476 return *this; | 578 return *this; |
477 } | 579 } |
478 | 580 |
479 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( | 581 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( |
480 Register object, Handle<ScopeInfo> scope_info) { | 582 Register object, Handle<ScopeInfo> scope_info) { |
481 size_t scope_info_index = GetConstantPoolEntry(scope_info); | 583 size_t scope_info_index = GetConstantPoolEntry(scope_info); |
482 Output(Bytecode::kCreateWithContext, RegisterOperand(object), | 584 OutputCreateWithContext(object, scope_info_index); |
483 UnsignedOperand(scope_info_index)); | |
484 return *this; | 585 return *this; |
485 } | 586 } |
486 | 587 |
487 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( | 588 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( |
488 CreateArgumentsType type) { | 589 CreateArgumentsType type) { |
489 switch (type) { | 590 switch (type) { |
490 case CreateArgumentsType::kMappedArguments: | 591 case CreateArgumentsType::kMappedArguments: |
491 Output(Bytecode::kCreateMappedArguments); | 592 OutputCreateMappedArguments(); |
492 break; | 593 break; |
493 case CreateArgumentsType::kUnmappedArguments: | 594 case CreateArgumentsType::kUnmappedArguments: |
494 Output(Bytecode::kCreateUnmappedArguments); | 595 OutputCreateUnmappedArguments(); |
495 break; | 596 break; |
496 case CreateArgumentsType::kRestParameter: | 597 case CreateArgumentsType::kRestParameter: |
497 Output(Bytecode::kCreateRestParameter); | 598 OutputCreateRestParameter(); |
498 break; | 599 break; |
499 default: | 600 default: |
500 UNREACHABLE(); | 601 UNREACHABLE(); |
501 } | 602 } |
502 return *this; | 603 return *this; |
503 } | 604 } |
504 | 605 |
505 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( | 606 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( |
506 Handle<String> pattern, int literal_index, int flags) { | 607 Handle<String> pattern, int literal_index, int flags) { |
507 size_t pattern_entry = GetConstantPoolEntry(pattern); | 608 size_t pattern_entry = GetConstantPoolEntry(pattern); |
508 Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry), | 609 OutputCreateRegExpLiteral(pattern_entry, literal_index, flags); |
509 UnsignedOperand(literal_index), UnsignedOperand(flags)); | |
510 return *this; | 610 return *this; |
511 } | 611 } |
512 | 612 |
513 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral( | 613 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral( |
514 Handle<FixedArray> constant_elements, int literal_index, int flags) { | 614 Handle<FixedArray> constant_elements, int literal_index, int flags) { |
515 size_t constant_elements_entry = GetConstantPoolEntry(constant_elements); | 615 size_t constant_elements_entry = GetConstantPoolEntry(constant_elements); |
516 Output(Bytecode::kCreateArrayLiteral, | 616 OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags); |
517 UnsignedOperand(constant_elements_entry), | |
518 UnsignedOperand(literal_index), UnsignedOperand(flags)); | |
519 return *this; | 617 return *this; |
520 } | 618 } |
521 | 619 |
522 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral( | 620 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral( |
523 Handle<FixedArray> constant_properties, int literal_index, int flags, | 621 Handle<FixedArray> constant_properties, int literal_index, int flags, |
524 Register output) { | 622 Register output) { |
525 size_t constant_properties_entry = GetConstantPoolEntry(constant_properties); | 623 size_t constant_properties_entry = GetConstantPoolEntry(constant_properties); |
526 Output(Bytecode::kCreateObjectLiteral, | 624 OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags, |
527 UnsignedOperand(constant_properties_entry), | 625 output); |
528 UnsignedOperand(literal_index), UnsignedOperand(flags), | |
529 RegisterOperand(output)); | |
530 return *this; | 626 return *this; |
531 } | 627 } |
532 | 628 |
533 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { | 629 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { |
534 Output(Bytecode::kPushContext, RegisterOperand(context)); | 630 OutputPushContext(context); |
535 return *this; | 631 return *this; |
536 } | 632 } |
537 | 633 |
538 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { | 634 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
539 Output(Bytecode::kPopContext, RegisterOperand(context)); | 635 OutputPopContext(context); |
540 return *this; | 636 return *this; |
541 } | 637 } |
542 | 638 |
543 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToObject( | 639 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToObject( |
544 Register out) { | 640 Register out) { |
545 Output(Bytecode::kToObject, RegisterOperand(out)); | 641 OutputToObject(out); |
546 return *this; | 642 return *this; |
547 } | 643 } |
548 | 644 |
549 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToName( | 645 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToName( |
550 Register out) { | 646 Register out) { |
551 Output(Bytecode::kToName, RegisterOperand(out)); | 647 OutputToName(out); |
552 return *this; | 648 return *this; |
553 } | 649 } |
554 | 650 |
555 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToNumber( | 651 BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToNumber( |
556 Register out) { | 652 Register out) { |
557 Output(Bytecode::kToNumber, RegisterOperand(out)); | 653 OutputToNumber(out); |
558 return *this; | 654 return *this; |
559 } | 655 } |
560 | 656 |
561 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) { | 657 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) { |
658 // Flush the register optimizer when binding a label to ensure all | |
659 // expected registers are valid when jumping to this label. | |
660 if (register_optimizer_) register_optimizer_->Flush(); | |
562 pipeline_->BindLabel(label); | 661 pipeline_->BindLabel(label); |
563 LeaveBasicBlock(); | 662 LeaveBasicBlock(); |
564 return *this; | 663 return *this; |
565 } | 664 } |
566 | 665 |
567 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, | 666 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, |
568 BytecodeLabel* label) { | 667 BytecodeLabel* label) { |
569 pipeline_->BindLabel(target, label); | 668 pipeline_->BindLabel(target, label); |
570 LeaveBasicBlock(); | 669 LeaveBasicBlock(); |
571 return *this; | 670 return *this; |
572 } | 671 } |
573 | 672 |
574 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { | 673 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { |
575 OutputJump(Bytecode::kJump, label); | 674 OutputJump(label, 0); |
576 return *this; | 675 return *this; |
577 } | 676 } |
578 | 677 |
579 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { | 678 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { |
580 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue | 679 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue |
581 // to JumpIfTrue. | 680 // to JumpIfTrue. |
582 OutputJump(Bytecode::kJumpIfToBooleanTrue, label); | 681 OutputJumpIfToBooleanTrue(label, 0); |
583 return *this; | 682 return *this; |
584 } | 683 } |
585 | 684 |
586 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { | 685 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { |
587 OutputJump(Bytecode::kJumpIfToBooleanFalse, label); | 686 OutputJumpIfToBooleanFalse(label, 0); |
588 return *this; | 687 return *this; |
589 } | 688 } |
590 | 689 |
591 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { | 690 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { |
592 OutputJump(Bytecode::kJumpIfNull, label); | 691 OutputJumpIfNull(label, 0); |
593 return *this; | 692 return *this; |
594 } | 693 } |
595 | 694 |
596 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( | 695 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( |
597 BytecodeLabel* label) { | 696 BytecodeLabel* label) { |
598 OutputJump(Bytecode::kJumpIfUndefined, label); | 697 OutputJumpIfUndefined(label, 0); |
599 return *this; | 698 return *this; |
600 } | 699 } |
601 | 700 |
602 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( | 701 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( |
603 BytecodeLabel* label) { | 702 BytecodeLabel* label) { |
604 OutputJump(Bytecode::kJumpIfNotHole, label); | 703 OutputJumpIfNotHole(label, 0); |
605 return *this; | 704 return *this; |
606 } | 705 } |
607 | 706 |
608 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, | 707 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, |
609 int loop_depth) { | 708 int loop_depth) { |
610 OutputJump(Bytecode::kJumpLoop, UnsignedOperand(loop_depth), label); | 709 OutputJumpLoop(label, 0, loop_depth); |
611 return *this; | 710 return *this; |
612 } | 711 } |
613 | 712 |
614 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { | 713 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { |
615 if (position != kNoSourcePosition) { | 714 if (position != kNoSourcePosition) { |
616 // We need to attach a non-breakable source position to a stack | 715 // We need to attach a non-breakable source position to a stack |
617 // check, so we simply add it as expression position. There can be | 716 // check, so we simply add it as expression position. There can be |
618 // a prior statement position from constructs like: | 717 // a prior statement position from constructs like: |
619 // | 718 // |
620 // do var x; while (false); | 719 // do var x; while (false); |
621 // | 720 // |
622 // A Nop could be inserted for empty statements, but since no code | 721 // A Nop could be inserted for empty statements, but since no code |
623 // is associated with these positions, instead we force the stack | 722 // is associated with these positions, instead we force the stack |
624 // check's expression position which eliminates the empty | 723 // check's expression position which eliminates the empty |
625 // statement's position. | 724 // statement's position. |
626 latest_source_info_.ForceExpressionPosition(position); | 725 latest_source_info_.ForceExpressionPosition(position); |
627 } | 726 } |
628 Output(Bytecode::kStackCheck); | 727 OutputStackCheck(); |
629 return *this; | 728 return *this; |
630 } | 729 } |
631 | 730 |
632 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { | 731 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { |
633 Output(Bytecode::kThrow); | 732 OutputThrow(); |
634 return *this; | 733 return *this; |
635 } | 734 } |
636 | 735 |
637 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() { | 736 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() { |
638 Output(Bytecode::kReThrow); | 737 OutputReThrow(); |
639 return *this; | 738 return *this; |
640 } | 739 } |
641 | 740 |
642 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { | 741 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { |
643 SetReturnPosition(); | 742 SetReturnPosition(); |
644 Output(Bytecode::kReturn); | 743 OutputReturn(); |
645 return_seen_in_block_ = true; | 744 return_seen_in_block_ = true; |
646 return *this; | 745 return *this; |
647 } | 746 } |
648 | 747 |
649 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { | 748 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { |
650 Output(Bytecode::kDebugger); | 749 OutputDebugger(); |
651 return *this; | 750 return *this; |
652 } | 751 } |
653 | 752 |
654 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( | 753 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( |
655 Register receiver, RegisterList cache_info_triple) { | 754 Register receiver, RegisterList cache_info_triple) { |
656 DCHECK_EQ(3, cache_info_triple.register_count()); | 755 DCHECK_EQ(3, cache_info_triple.register_count()); |
657 Output(Bytecode::kForInPrepare, RegisterOperand(receiver), | 756 OutputForInPrepare(receiver, cache_info_triple); |
658 RegisterOperand(cache_info_triple.first_register())); | |
659 return *this; | 757 return *this; |
660 } | 758 } |
661 | 759 |
662 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue( | 760 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue( |
663 Register index, Register cache_length) { | 761 Register index, Register cache_length) { |
664 Output(Bytecode::kForInContinue, RegisterOperand(index), | 762 OutputForInContinue(index, cache_length); |
665 RegisterOperand(cache_length)); | |
666 return *this; | 763 return *this; |
667 } | 764 } |
668 | 765 |
669 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( | 766 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( |
670 Register receiver, Register index, RegisterList cache_type_array_pair, | 767 Register receiver, Register index, RegisterList cache_type_array_pair, |
671 int feedback_slot) { | 768 int feedback_slot) { |
672 DCHECK_EQ(2, cache_type_array_pair.register_count()); | 769 DCHECK_EQ(2, cache_type_array_pair.register_count()); |
673 Output(Bytecode::kForInNext, RegisterOperand(receiver), | 770 OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot); |
674 RegisterOperand(index), | |
675 RegisterOperand(cache_type_array_pair.first_register()), | |
676 UnsignedOperand(feedback_slot)); | |
677 return *this; | 771 return *this; |
678 } | 772 } |
679 | 773 |
680 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { | 774 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { |
681 Output(Bytecode::kForInStep, RegisterOperand(index)); | 775 OutputForInStep(index); |
682 return *this; | 776 return *this; |
683 } | 777 } |
684 | 778 |
685 BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator( | 779 BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator( |
686 Register generator) { | 780 Register generator) { |
687 Output(Bytecode::kSuspendGenerator, RegisterOperand(generator)); | 781 OutputSuspendGenerator(generator); |
688 return *this; | 782 return *this; |
689 } | 783 } |
690 | 784 |
691 BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator( | 785 BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator( |
692 Register generator) { | 786 Register generator) { |
693 Output(Bytecode::kResumeGenerator, RegisterOperand(generator)); | 787 OutputResumeGenerator(generator); |
694 return *this; | 788 return *this; |
695 } | 789 } |
696 | 790 |
697 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler( | 791 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler( |
698 int handler_id, HandlerTable::CatchPrediction catch_prediction) { | 792 int handler_id, HandlerTable::CatchPrediction catch_prediction) { |
699 BytecodeLabel handler; | 793 BytecodeLabel handler; |
700 Bind(&handler); | 794 Bind(&handler); |
701 handler_table_builder()->SetHandlerTarget(handler_id, handler.offset()); | 795 handler_table_builder()->SetHandlerTarget(handler_id, handler.offset()); |
702 handler_table_builder()->SetPrediction(handler_id, catch_prediction); | 796 handler_table_builder()->SetPrediction(handler_id, catch_prediction); |
703 return *this; | 797 return *this; |
(...skipping 13 matching lines...) Expand all Loading... | |
717 Bind(&try_end); | 811 Bind(&try_end); |
718 handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset()); | 812 handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset()); |
719 return *this; | 813 return *this; |
720 } | 814 } |
721 | 815 |
722 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 816 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
723 RegisterList args, | 817 RegisterList args, |
724 int feedback_slot, | 818 int feedback_slot, |
725 TailCallMode tail_call_mode) { | 819 TailCallMode tail_call_mode) { |
726 if (tail_call_mode == TailCallMode::kDisallow) { | 820 if (tail_call_mode == TailCallMode::kDisallow) { |
727 Output(Bytecode::kCall, RegisterOperand(callable), | 821 OutputCall(callable, args, args.register_count(), feedback_slot); |
728 RegisterOperand(args.first_register()), | |
729 UnsignedOperand(args.register_count()), | |
730 UnsignedOperand(feedback_slot)); | |
731 } else { | 822 } else { |
732 DCHECK(tail_call_mode == TailCallMode::kAllow); | 823 DCHECK(tail_call_mode == TailCallMode::kAllow); |
733 Output(Bytecode::kTailCall, RegisterOperand(callable), | 824 OutputTailCall(callable, args, args.register_count(), feedback_slot); |
734 RegisterOperand(args.first_register()), | |
735 UnsignedOperand(args.register_count()), | |
736 UnsignedOperand(feedback_slot)); | |
737 } | 825 } |
738 return *this; | 826 return *this; |
739 } | 827 } |
740 | 828 |
741 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 829 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
742 RegisterList args, | 830 RegisterList args, |
743 int feedback_slot_id) { | 831 int feedback_slot_id) { |
744 Output(Bytecode::kNew, RegisterOperand(constructor), | 832 OutputNew(constructor, args, args.register_count(), feedback_slot_id); |
745 RegisterOperand(args.first_register()), | |
746 UnsignedOperand(args.register_count()), | |
747 UnsignedOperand(feedback_slot_id)); | |
748 return *this; | 833 return *this; |
749 } | 834 } |
750 | 835 |
751 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 836 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
752 Runtime::FunctionId function_id, RegisterList args) { | 837 Runtime::FunctionId function_id, RegisterList args) { |
753 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); | 838 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); |
754 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); | 839 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
755 Bytecode bytecode; | |
756 uint32_t id; | |
757 if (IntrinsicsHelper::IsSupported(function_id)) { | 840 if (IntrinsicsHelper::IsSupported(function_id)) { |
758 bytecode = Bytecode::kInvokeIntrinsic; | 841 IntrinsicsHelper::IntrinsicId intrinsic_id = |
759 id = static_cast<uint32_t>(IntrinsicsHelper::FromRuntimeId(function_id)); | 842 IntrinsicsHelper::FromRuntimeId(function_id); |
843 OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args, | |
844 args.register_count()); | |
760 } else { | 845 } else { |
761 bytecode = Bytecode::kCallRuntime; | 846 OutputCallRuntime(static_cast<int>(function_id), args, |
762 id = static_cast<uint32_t>(function_id); | 847 args.register_count()); |
763 } | 848 } |
764 Output(bytecode, id, RegisterOperand(args.first_register()), | |
765 UnsignedOperand(args.register_count())); | |
766 return *this; | 849 return *this; |
767 } | 850 } |
768 | 851 |
769 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 852 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
770 Runtime::FunctionId function_id, Register arg) { | 853 Runtime::FunctionId function_id, Register arg) { |
771 return CallRuntime(function_id, RegisterList(arg.index(), 1)); | 854 return CallRuntime(function_id, RegisterList(arg.index(), 1)); |
772 } | 855 } |
773 | 856 |
774 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 857 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
775 Runtime::FunctionId function_id) { | 858 Runtime::FunctionId function_id) { |
776 return CallRuntime(function_id, RegisterList()); | 859 return CallRuntime(function_id, RegisterList()); |
777 } | 860 } |
778 | 861 |
779 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( | 862 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
780 Runtime::FunctionId function_id, RegisterList args, | 863 Runtime::FunctionId function_id, RegisterList args, |
781 RegisterList return_pair) { | 864 RegisterList return_pair) { |
782 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); | 865 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); |
783 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); | 866 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
784 DCHECK_EQ(2, return_pair.register_count()); | 867 DCHECK_EQ(2, return_pair.register_count()); |
785 Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id), | 868 OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args, |
786 RegisterOperand(args.first_register()), | 869 args.register_count(), return_pair); |
787 UnsignedOperand(args.register_count()), | |
788 RegisterOperand(return_pair.first_register())); | |
789 return *this; | 870 return *this; |
790 } | 871 } |
791 | 872 |
792 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( | 873 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
793 Runtime::FunctionId function_id, Register arg, RegisterList return_pair) { | 874 Runtime::FunctionId function_id, Register arg, RegisterList return_pair) { |
794 return CallRuntimeForPair(function_id, RegisterList(arg.index(), 1), | 875 return CallRuntimeForPair(function_id, RegisterList(arg.index(), 1), |
795 return_pair); | 876 return_pair); |
796 } | 877 } |
797 | 878 |
798 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index, | 879 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index, |
799 RegisterList args) { | 880 RegisterList args) { |
800 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), | 881 OutputCallJSRuntime(context_index, args, args.register_count()); |
801 RegisterOperand(args.first_register()), | |
802 UnsignedOperand(args.register_count())); | |
803 return *this; | 882 return *this; |
804 } | 883 } |
805 | 884 |
806 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, | 885 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
807 LanguageMode language_mode) { | 886 LanguageMode language_mode) { |
808 if (language_mode == SLOPPY) { | 887 if (language_mode == SLOPPY) { |
809 Output(Bytecode::kDeletePropertySloppy, RegisterOperand(object)); | 888 OutputDeletePropertySloppy(object); |
810 } else { | 889 } else { |
811 DCHECK_EQ(language_mode, STRICT); | 890 DCHECK_EQ(language_mode, STRICT); |
812 Output(Bytecode::kDeletePropertyStrict, RegisterOperand(object)); | 891 OutputDeletePropertyStrict(object); |
813 } | 892 } |
814 return *this; | 893 return *this; |
815 } | 894 } |
816 | 895 |
817 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 896 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
818 return constant_array_builder()->Insert(object); | 897 return constant_array_builder()->Insert(object); |
819 } | 898 } |
820 | 899 |
821 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { | 900 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { |
822 return constant_array_builder()->AllocateEntry(); | 901 return constant_array_builder()->AllocateEntry(); |
(...skipping 20 matching lines...) Expand all Loading... | |
843 } else if (reg.is_parameter()) { | 922 } else if (reg.is_parameter()) { |
844 int parameter_index = reg.ToParameterIndex(parameter_count()); | 923 int parameter_index = reg.ToParameterIndex(parameter_count()); |
845 return parameter_index >= 0 && parameter_index < parameter_count(); | 924 return parameter_index >= 0 && parameter_index < parameter_count(); |
846 } else if (reg.index() < fixed_register_count()) { | 925 } else if (reg.index() < fixed_register_count()) { |
847 return true; | 926 return true; |
848 } else { | 927 } else { |
849 return register_allocator()->RegisterIsLive(reg); | 928 return register_allocator()->RegisterIsLive(reg); |
850 } | 929 } |
851 } | 930 } |
852 | 931 |
853 bool BytecodeArrayBuilder::OperandsAreValid( | 932 bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const { |
854 Bytecode bytecode, int operand_count, uint32_t operand0, uint32_t operand1, | 933 if (reg_list.register_count() == 0) { |
855 uint32_t operand2, uint32_t operand3) const { | 934 return reg_list.first_register() == Register(0); |
856 if (Bytecodes::NumberOfOperands(bytecode) != operand_count) { | 935 } else { |
857 return false; | 936 int first_reg_index = reg_list.first_register().index(); |
937 for (int i = 0; i < reg_list.register_count(); i++) { | |
938 if (!RegisterIsValid(Register(first_reg_index + i))) { | |
939 return false; | |
940 } | |
941 } | |
942 return true; | |
858 } | 943 } |
944 } | |
859 | 945 |
860 uint32_t operands[] = {operand0, operand1, operand2, operand3}; | 946 void BytecodeArrayBuilder::PrepareToOutputBytecode(Bytecode bytecode) { |
861 const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode); | 947 if (register_optimizer_) register_optimizer_->PrepareForBytecode(bytecode); |
862 for (int i = 0; i < operand_count; ++i) { | 948 } |
863 switch (operand_types[i]) { | |
864 case OperandType::kNone: | |
865 return false; | |
866 case OperandType::kFlag8: | |
867 case OperandType::kIntrinsicId: | |
868 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > | |
869 OperandSize::kByte) { | |
870 return false; | |
871 } | |
872 break; | |
873 case OperandType::kRuntimeId: | |
874 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > | |
875 OperandSize::kShort) { | |
876 return false; | |
877 } | |
878 break; | |
879 case OperandType::kIdx: | |
880 // TODO(leszeks): Possibly split this up into constant pool indices and | |
881 // other indices, for checking. | |
882 break; | |
883 case OperandType::kUImm: | |
884 case OperandType::kImm: | |
885 break; | |
886 case OperandType::kRegList: { | |
887 CHECK_LT(i, operand_count - 1); | |
888 CHECK(operand_types[i + 1] == OperandType::kRegCount); | |
889 int reg_count = static_cast<int>(operands[i + 1]); | |
890 if (reg_count == 0) { | |
891 return Register::FromOperand(operands[i]) == Register(0); | |
892 } else { | |
893 Register start = Register::FromOperand(operands[i]); | |
894 Register end(start.index() + reg_count - 1); | |
895 if (!RegisterIsValid(start) || !RegisterIsValid(end) || start > end) { | |
896 return false; | |
897 } | |
898 } | |
899 i++; // Skip past kRegCount operand. | |
900 break; | |
901 } | |
902 case OperandType::kReg: | |
903 case OperandType::kRegOut: { | |
904 Register reg = Register::FromOperand(operands[i]); | |
905 if (!RegisterIsValid(reg)) { | |
906 return false; | |
907 } | |
908 break; | |
909 } | |
910 case OperandType::kRegOutPair: | |
911 case OperandType::kRegPair: { | |
912 Register reg0 = Register::FromOperand(operands[i]); | |
913 Register reg1 = Register(reg0.index() + 1); | |
914 if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1)) { | |
915 return false; | |
916 } | |
917 break; | |
918 } | |
919 case OperandType::kRegOutTriple: { | |
920 Register reg0 = Register::FromOperand(operands[i]); | |
921 Register reg1 = Register(reg0.index() + 1); | |
922 Register reg2 = Register(reg0.index() + 2); | |
923 if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1) || | |
924 !RegisterIsValid(reg2)) { | |
925 return false; | |
926 } | |
927 break; | |
928 } | |
929 case OperandType::kRegCount: | |
930 UNREACHABLE(); // Dealt with in kRegList above. | |
931 } | |
932 } | |
933 | 949 |
934 return true; | 950 uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) { |
951 DCHECK(RegisterIsValid(reg)); | |
952 if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg); | |
953 return static_cast<uint32_t>(reg.ToOperand()); | |
954 } | |
955 | |
956 uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) { | |
957 DCHECK(RegisterIsValid(reg)); | |
958 if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg); | |
959 return static_cast<uint32_t>(reg.ToOperand()); | |
960 } | |
961 | |
962 uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand( | |
963 RegisterList reg_list) { | |
964 DCHECK(RegisterListIsValid(reg_list)); | |
965 if (register_optimizer_) | |
966 reg_list = register_optimizer_->GetInputRegisterList(reg_list); | |
967 return static_cast<uint32_t>(reg_list.first_register().ToOperand()); | |
968 } | |
969 | |
970 uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand( | |
971 RegisterList reg_list) { | |
972 DCHECK(RegisterListIsValid(reg_list)); | |
973 if (register_optimizer_) | |
974 register_optimizer_->PrepareOutputRegisterList(reg_list); | |
975 return static_cast<uint32_t>(reg_list.first_register().ToOperand()); | |
935 } | 976 } |
936 | 977 |
937 } // namespace interpreter | 978 } // namespace interpreter |
938 } // namespace internal | 979 } // namespace internal |
939 } // namespace v8 | 980 } // namespace v8 |
OLD | NEW |