Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(624)

Side by Side Diff: src/interpreter/bytecode-array-builder.cc

Issue 2393683004: [Interpreter] Optimize the Register Optimizer. (Closed)
Patch Set: Fix unused variable in test Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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, &register_allocator_, fixed_register_count(), parameter_count, 50 zone, &register_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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698