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

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

Issue 2393683004: [Interpreter] Optimize the Register Optimizer. (Closed)
Patch Set: Rebase Created 4 years, 1 month 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
« no previous file with comments | « src/interpreter/bytecode-array-builder.h ('k') | src/interpreter/bytecode-operands.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_);
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
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
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
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-array-builder.h ('k') | src/interpreter/bytecode-operands.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698