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