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

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

Issue 2351763002: [Interpreter] Optimize BytecodeArrayBuilder and BytecodeArrayWriter. (Closed)
Patch Set: [Interpreter] Optimize BytecodeArrayBuilder and BytecodeArrayWriter. Created 4 years, 3 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 return reg.is_parameter() || reg.index() < locals_count(); 73 return reg.is_parameter() || reg.index() < locals_count();
74 } 74 }
75 75
76 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { 76 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
77 DCHECK(return_seen_in_block_); 77 DCHECK(return_seen_in_block_);
78 DCHECK(!bytecode_generated_); 78 DCHECK(!bytecode_generated_);
79 bytecode_generated_ = true; 79 bytecode_generated_ = true;
80 80
81 Handle<FixedArray> handler_table = 81 Handle<FixedArray> handler_table =
82 handler_table_builder()->ToHandlerTable(isolate); 82 handler_table_builder()->ToHandlerTable(isolate);
83 return pipeline_->ToBytecodeArray(isolate, fixed_register_count(), 83 return pipeline_->ToBytecodeArray(isolate,
84 fixed_and_temporary_register_count(),
84 parameter_count(), handler_table); 85 parameter_count(), handler_table);
85 } 86 }
86 87
87 namespace {
88
89 static bool ExpressionPositionIsNeeded(Bytecode bytecode) {
90 // An expression position is always needed if filtering is turned
91 // off. Otherwise an expression is only needed if the bytecode has
92 // external side effects.
93 return !FLAG_ignition_filter_expression_positions ||
94 !Bytecodes::IsWithoutExternalSideEffects(bytecode);
95 }
96
97 } // namespace
98
99 void BytecodeArrayBuilder::AttachSourceInfo(BytecodeNode* node) {
100 if (latest_source_info_.is_valid()) {
101 // Statement positions need to be emitted immediately. Expression
102 // positions can be pushed back until a bytecode is found that can
103 // throw. Hence we only invalidate the existing source position
104 // information if it is used.
105 if (latest_source_info_.is_statement() ||
106 ExpressionPositionIsNeeded(node->bytecode())) {
107 node->source_info().Clone(latest_source_info_);
108 latest_source_info_.set_invalid();
109 }
110 }
111 }
112
113 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, 88 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
114 uint32_t operand1, uint32_t operand2, 89 uint32_t operand1, uint32_t operand2,
115 uint32_t operand3) { 90 uint32_t operand3) {
116 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); 91 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3));
117 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3); 92 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3,
118 AttachSourceInfo(&node); 93 &latest_source_info_);
119 pipeline()->Write(&node); 94 pipeline()->Write(&node);
120 } 95 }
121 96
122 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, 97 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
123 uint32_t operand1, uint32_t operand2) { 98 uint32_t operand1, uint32_t operand2) {
124 DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2)); 99 DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2));
125 BytecodeNode node(bytecode, operand0, operand1, operand2); 100 BytecodeNode node(bytecode, operand0, operand1, operand2,
126 AttachSourceInfo(&node); 101 &latest_source_info_);
127 pipeline()->Write(&node); 102 pipeline()->Write(&node);
128 } 103 }
129 104
130 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, 105 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
131 uint32_t operand1) { 106 uint32_t operand1) {
132 DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1)); 107 DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1));
133 BytecodeNode node(bytecode, operand0, operand1); 108 BytecodeNode node(bytecode, operand0, operand1, &latest_source_info_);
134 AttachSourceInfo(&node);
135 pipeline()->Write(&node); 109 pipeline()->Write(&node);
136 } 110 }
137 111
138 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { 112 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) {
139 DCHECK(OperandsAreValid(bytecode, 1, operand0)); 113 DCHECK(OperandsAreValid(bytecode, 1, operand0));
140 BytecodeNode node(bytecode, operand0); 114 BytecodeNode node(bytecode, operand0, &latest_source_info_);
141 AttachSourceInfo(&node);
142 pipeline()->Write(&node); 115 pipeline()->Write(&node);
143 } 116 }
144 117
145 void BytecodeArrayBuilder::Output(Bytecode bytecode) { 118 void BytecodeArrayBuilder::Output(Bytecode bytecode) {
146 DCHECK(OperandsAreValid(bytecode, 0)); 119 DCHECK(OperandsAreValid(bytecode, 0));
147 BytecodeNode node(bytecode); 120 BytecodeNode node(bytecode, &latest_source_info_);
148 AttachSourceInfo(&node);
149 pipeline()->Write(&node); 121 pipeline()->Write(&node);
150 } 122 }
151 123
124 void BytecodeArrayBuilder::OutputJump(Bytecode bytecode,
125 BytecodeLabel* label) {
126 BytecodeNode node(bytecode, 0, &latest_source_info_);
127 pipeline_->WriteJump(&node, label);
128 LeaveBasicBlock();
129 }
130
131 void BytecodeArrayBuilder::OutputJump(Bytecode bytecode,
132 uint32_t operand0, BytecodeLabel* label) {
133 BytecodeNode node(bytecode, 0, operand0, &latest_source_info_);
134 pipeline_->WriteJump(&node, label);
135 LeaveBasicBlock();
136 }
137
152 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, 138 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
153 Register reg, 139 Register reg,
154 int feedback_slot) { 140 int feedback_slot) {
155 Output(BytecodeForBinaryOperation(op), RegisterOperand(reg), 141 switch (op) {
156 UnsignedOperand(feedback_slot)); 142 case Token::Value::ADD:
143 Output(Bytecode::kAdd, RegisterOperand(reg),
144 UnsignedOperand(feedback_slot));
145 break;
146 case Token::Value::SUB:
147 Output(Bytecode::kSub, RegisterOperand(reg),
148 UnsignedOperand(feedback_slot));
149 break;
150 case Token::Value::MUL:
151 Output(Bytecode::kMul, RegisterOperand(reg),
152 UnsignedOperand(feedback_slot));
153 break;
154 case Token::Value::DIV:
155 Output(Bytecode::kDiv, RegisterOperand(reg),
156 UnsignedOperand(feedback_slot));
157 break;
158 case Token::Value::MOD:
159 Output(Bytecode::kMod, RegisterOperand(reg),
160 UnsignedOperand(feedback_slot));
161 break;
162 case Token::Value::BIT_OR:
163 Output(Bytecode::kBitwiseOr, RegisterOperand(reg),
164 UnsignedOperand(feedback_slot));
165 break;
166 case Token::Value::BIT_XOR:
167 Output(Bytecode::kBitwiseXor, RegisterOperand(reg),
168 UnsignedOperand(feedback_slot));
169 break;
170 case Token::Value::BIT_AND:
171 Output(Bytecode::kBitwiseAnd, RegisterOperand(reg),
172 UnsignedOperand(feedback_slot));
173 break;
174 case Token::Value::SHL:
175 Output(Bytecode::kShiftLeft, RegisterOperand(reg),
176 UnsignedOperand(feedback_slot));
177 break;
178 case Token::Value::SAR:
179 Output(Bytecode::kShiftRight, RegisterOperand(reg),
180 UnsignedOperand(feedback_slot));
181 break;
182 case Token::Value::SHR:
183 Output(Bytecode::kShiftRightLogical, RegisterOperand(reg),
184 UnsignedOperand(feedback_slot));
185 break;
186 default:
187 UNREACHABLE();
188 }
157 return *this; 189 return *this;
158 } 190 }
159 191
160 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, 192 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op,
161 int feedback_slot) { 193 int feedback_slot) {
162 Output(BytecodeForCountOperation(op), UnsignedOperand(feedback_slot)); 194 if (op == Token::Value::ADD) {
195 Output(Bytecode::kInc, UnsignedOperand(feedback_slot));
196 } else {
197 DCHECK_EQ(op, Token::Value::SUB);
198 Output(Bytecode::kDec, UnsignedOperand(feedback_slot));
199 }
163 return *this; 200 return *this;
164 } 201 }
165 202
166 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { 203 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() {
167 Output(Bytecode::kToBooleanLogicalNot); 204 Output(Bytecode::kToBooleanLogicalNot);
168 return *this; 205 return *this;
169 } 206 }
170 207
171
172 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { 208 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
173 Output(Bytecode::kTypeOf); 209 Output(Bytecode::kTypeOf);
174 return *this; 210 return *this;
175 } 211 }
176 212
177 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( 213 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
178 Token::Value op, Register reg, int feedback_slot) { 214 Token::Value op, Register reg, int feedback_slot) {
179 if (op == Token::INSTANCEOF || op == Token::IN) { 215 switch (op) {
180 Output(BytecodeForCompareOperation(op), RegisterOperand(reg)); 216 case Token::Value::EQ:
181 } else { 217 Output(Bytecode::kTestEqual, RegisterOperand(reg),
182 Output(BytecodeForCompareOperation(op), RegisterOperand(reg), 218 UnsignedOperand(feedback_slot));
183 UnsignedOperand(feedback_slot)); 219 break;
220 case Token::Value::NE:
221 Output(Bytecode::kTestNotEqual, RegisterOperand(reg),
222 UnsignedOperand(feedback_slot));
223 break;
224 case Token::Value::EQ_STRICT:
225 Output(Bytecode::kTestEqualStrict, RegisterOperand(reg),
226 UnsignedOperand(feedback_slot));
227 break;
228 case Token::Value::LT:
229 Output(Bytecode::kTestLessThan, RegisterOperand(reg),
230 UnsignedOperand(feedback_slot));
231 break;
232 case Token::Value::GT:
233 Output(Bytecode::kTestGreaterThan, RegisterOperand(reg),
234 UnsignedOperand(feedback_slot));
235 break;
236 case Token::Value::LTE:
237 Output(Bytecode::kTestLessThanOrEqual, RegisterOperand(reg),
238 UnsignedOperand(feedback_slot));
239 break;
240 case Token::Value::GTE:
241 Output(Bytecode::kTestGreaterThanOrEqual, RegisterOperand(reg),
242 UnsignedOperand(feedback_slot));
243 break;
244 case Token::Value::INSTANCEOF:
245 Output(Bytecode::kTestInstanceOf, RegisterOperand(reg));
246 break;
247 case Token::Value::IN:
248 Output(Bytecode::kTestIn, RegisterOperand(reg));
249 break;
250 default:
251 UNREACHABLE();
184 } 252 }
185 return *this; 253 return *this;
186 } 254 }
187 255
188 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( 256 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
189 size_t entry) { 257 size_t entry) {
190 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); 258 Output(Bytecode::kLdaConstant, UnsignedOperand(entry));
191 return *this; 259 return *this;
192 } 260 }
193 261
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 315
248 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, 316 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
249 Register to) { 317 Register to) {
250 DCHECK(from != to); 318 DCHECK(from != to);
251 Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to)); 319 Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to));
252 return *this; 320 return *this;
253 } 321 }
254 322
255 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, 323 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot,
256 TypeofMode typeof_mode) { 324 TypeofMode typeof_mode) {
257 // TODO(rmcilroy): Potentially store typeof information in an 325 if (typeof_mode == INSIDE_TYPEOF) {
258 // operand rather than having extra bytecodes. 326 Output(Bytecode::kLdaGlobalInsideTypeof, feedback_slot);
259 Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode); 327 } else {
260 Output(bytecode, UnsignedOperand(feedback_slot)); 328 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
329 Output(Bytecode::kLdaGlobal, UnsignedOperand(feedback_slot));
330 }
261 return *this; 331 return *this;
262 } 332 }
263 333
264 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( 334 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
265 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { 335 const Handle<String> name, int feedback_slot, LanguageMode language_mode) {
266 Bytecode bytecode = BytecodeForStoreGlobal(language_mode);
267 size_t name_index = GetConstantPoolEntry(name); 336 size_t name_index = GetConstantPoolEntry(name);
268 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); 337 if (language_mode == SLOPPY) {
338 Output(Bytecode::kStaGlobalSloppy, UnsignedOperand(name_index),
339 UnsignedOperand(feedback_slot));
340 } else {
341 DCHECK_EQ(language_mode, STRICT);
342 Output(Bytecode::kStaGlobalStrict, UnsignedOperand(name_index),
343 UnsignedOperand(feedback_slot));
344 }
269 return *this; 345 return *this;
270 } 346 }
271 347
272 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, 348 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context,
273 int slot_index, 349 int slot_index,
274 int depth) { 350 int depth) {
275 Output(Bytecode::kLdaContextSlot, RegisterOperand(context), 351 Output(Bytecode::kLdaContextSlot, RegisterOperand(context),
276 UnsignedOperand(slot_index), UnsignedOperand(depth)); 352 UnsignedOperand(slot_index), UnsignedOperand(depth));
277 return *this; 353 return *this;
278 } 354 }
279 355
280 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, 356 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
281 int slot_index, 357 int slot_index,
282 int depth) { 358 int depth) {
283 Output(Bytecode::kStaContextSlot, RegisterOperand(context), 359 Output(Bytecode::kStaContextSlot, RegisterOperand(context),
284 UnsignedOperand(slot_index), UnsignedOperand(depth)); 360 UnsignedOperand(slot_index), UnsignedOperand(depth));
285 return *this; 361 return *this;
286 } 362 }
287 363
288 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( 364 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
289 const Handle<String> name, TypeofMode typeof_mode) { 365 const Handle<String> name, TypeofMode typeof_mode) {
290 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF)
291 ? Bytecode::kLdaLookupSlotInsideTypeof
292 : Bytecode::kLdaLookupSlot;
293 size_t name_index = GetConstantPoolEntry(name); 366 size_t name_index = GetConstantPoolEntry(name);
294 Output(bytecode, UnsignedOperand(name_index)); 367 if (typeof_mode == INSIDE_TYPEOF) {
368 Output(Bytecode::kLdaLookupSlotInsideTypeof, UnsignedOperand(name_index));
369 } else {
370 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF);
371 Output(Bytecode::kLdaLookupSlot, UnsignedOperand(name_index));
372 }
295 return *this; 373 return *this;
296 } 374 }
297 375
298 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( 376 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
299 const Handle<String> name, LanguageMode language_mode) { 377 const Handle<String> name, LanguageMode language_mode) {
300 Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode);
301 size_t name_index = GetConstantPoolEntry(name); 378 size_t name_index = GetConstantPoolEntry(name);
302 Output(bytecode, UnsignedOperand(name_index)); 379 if (language_mode == SLOPPY) {
380 Output(Bytecode::kStaLookupSlotSloppy, UnsignedOperand(name_index));
381 } else {
Leszek Swirski 2016/09/20 10:37:56 DCHECK for strict
rmcilroy 2016/09/20 16:57:25 Done.
382 Output(Bytecode::kStaLookupSlotStrict, UnsignedOperand(name_index));
383 }
303 return *this; 384 return *this;
304 } 385 }
305 386
306 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( 387 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
307 Register object, const Handle<Name> name, int feedback_slot) { 388 Register object, const Handle<Name> name, int feedback_slot) {
308 size_t name_index = GetConstantPoolEntry(name); 389 size_t name_index = GetConstantPoolEntry(name);
309 Output(Bytecode::kLdaNamedProperty, RegisterOperand(object), 390 Output(Bytecode::kLdaNamedProperty, RegisterOperand(object),
310 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); 391 UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
311 return *this; 392 return *this;
312 } 393 }
313 394
314 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( 395 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
315 Register object, int feedback_slot) { 396 Register object, int feedback_slot) {
316 Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object), 397 Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object),
317 UnsignedOperand(feedback_slot)); 398 UnsignedOperand(feedback_slot));
318 return *this; 399 return *this;
319 } 400 }
320 401
321 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( 402 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
322 Register object, const Handle<Name> name, int feedback_slot, 403 Register object, const Handle<Name> name, int feedback_slot,
323 LanguageMode language_mode) { 404 LanguageMode language_mode) {
324 Bytecode bytecode = BytecodeForStoreNamedProperty(language_mode);
325 size_t name_index = GetConstantPoolEntry(name); 405 size_t name_index = GetConstantPoolEntry(name);
326 Output(bytecode, RegisterOperand(object), UnsignedOperand(name_index), 406 if (language_mode == SLOPPY) {
327 UnsignedOperand(feedback_slot)); 407 Output(Bytecode::kStaNamedPropertySloppy, RegisterOperand(object),
408 UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
409 } else {
410 DCHECK_EQ(language_mode, STRICT);
411 Output(Bytecode::kStaNamedPropertyStrict, RegisterOperand(object),
412 UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
413 }
328 return *this; 414 return *this;
329 } 415 }
330 416
331 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( 417 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
332 Register object, Register key, int feedback_slot, 418 Register object, Register key, int feedback_slot,
333 LanguageMode language_mode) { 419 LanguageMode language_mode) {
334 Bytecode bytecode = BytecodeForStoreKeyedProperty(language_mode); 420 if (language_mode == SLOPPY) {
335 Output(bytecode, RegisterOperand(object), RegisterOperand(key), 421 Output(Bytecode::kStaKeyedPropertySloppy, RegisterOperand(object),
336 UnsignedOperand(feedback_slot)); 422 RegisterOperand(key), UnsignedOperand(feedback_slot));
423 } else {
424 DCHECK_EQ(language_mode, STRICT);
425 Output(Bytecode::kStaKeyedPropertyStrict, RegisterOperand(object),
426 RegisterOperand(key), UnsignedOperand(feedback_slot));
427 }
337 return *this; 428 return *this;
338 } 429 }
339 430
340 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, 431 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry,
341 int flags) { 432 int flags) {
342 Output(Bytecode::kCreateClosure, UnsignedOperand(entry), 433 Output(Bytecode::kCreateClosure, UnsignedOperand(entry),
343 UnsignedOperand(flags)); 434 UnsignedOperand(flags));
344 return *this; 435 return *this;
345 } 436 }
346 437
(...skipping 21 matching lines...) Expand all
368 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( 459 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
369 Register object, Handle<ScopeInfo> scope_info) { 460 Register object, Handle<ScopeInfo> scope_info) {
370 size_t scope_info_index = GetConstantPoolEntry(scope_info); 461 size_t scope_info_index = GetConstantPoolEntry(scope_info);
371 Output(Bytecode::kCreateWithContext, RegisterOperand(object), 462 Output(Bytecode::kCreateWithContext, RegisterOperand(object),
372 UnsignedOperand(scope_info_index)); 463 UnsignedOperand(scope_info_index));
373 return *this; 464 return *this;
374 } 465 }
375 466
376 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( 467 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
377 CreateArgumentsType type) { 468 CreateArgumentsType type) {
378 // TODO(rmcilroy): Consider passing the type as a bytecode operand rather 469 switch (type) {
379 // than having two different bytecodes once we have better support for 470 case CreateArgumentsType::kMappedArguments:
380 // branches in the InterpreterAssembler. 471 Output(Bytecode::kCreateMappedArguments);
381 Bytecode bytecode = BytecodeForCreateArguments(type); 472 break;
382 Output(bytecode); 473 case CreateArgumentsType::kUnmappedArguments:
474 Output(Bytecode::kCreateUnmappedArguments);
475 break;
476 case CreateArgumentsType::kRestParameter:
477 Output(Bytecode::kCreateRestParameter);
478 break;
479 default:
480 UNREACHABLE();
481 }
383 return *this; 482 return *this;
384 } 483 }
385 484
386 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( 485 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
387 Handle<String> pattern, int literal_index, int flags) { 486 Handle<String> pattern, int literal_index, int flags) {
388 size_t pattern_entry = GetConstantPoolEntry(pattern); 487 size_t pattern_entry = GetConstantPoolEntry(pattern);
389 Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry), 488 Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry),
390 UnsignedOperand(literal_index), UnsignedOperand(flags)); 489 UnsignedOperand(literal_index), UnsignedOperand(flags));
391 return *this; 490 return *this;
392 } 491 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 return *this; 544 return *this;
446 } 545 }
447 546
448 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, 547 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
449 BytecodeLabel* label) { 548 BytecodeLabel* label) {
450 pipeline_->BindLabel(target, label); 549 pipeline_->BindLabel(target, label);
451 LeaveBasicBlock(); 550 LeaveBasicBlock();
452 return *this; 551 return *this;
453 } 552 }
454 553
455 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(BytecodeNode* node,
456 BytecodeLabel* label) {
457 AttachSourceInfo(node);
458 pipeline_->WriteJump(node, label);
459 LeaveBasicBlock();
460 return *this;
461 }
462
463 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { 554 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
464 BytecodeNode node(Bytecode::kJump, 0); 555 OutputJump(Bytecode::kJump, label);
465 return OutputJump(&node, label); 556 return *this;
466 } 557 }
467 558
468 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { 559 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
469 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue 560 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue
470 // to JumpIfTrue. 561 // to JumpIfTrue.
471 BytecodeNode node(Bytecode::kJumpIfToBooleanTrue, 0); 562 OutputJump(Bytecode::kJumpIfToBooleanTrue, label);
472 return OutputJump(&node, label); 563 return *this;
473 } 564 }
474 565
475 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { 566 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
476 // The peephole optimizer attempts to simplify JumpIfToBooleanFalse 567 OutputJump(Bytecode::kJumpIfToBooleanFalse, label);
477 // to JumpIfFalse. 568 return *this;
478 BytecodeNode node(Bytecode::kJumpIfToBooleanFalse, 0);
479 return OutputJump(&node, label);
480 } 569 }
481 570
482 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { 571 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
483 BytecodeNode node(Bytecode::kJumpIfNull, 0); 572 OutputJump(Bytecode::kJumpIfNull, label);
484 return OutputJump(&node, label); 573 return *this;
485 } 574 }
486 575
487 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( 576 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
488 BytecodeLabel* label) { 577 BytecodeLabel* label) {
489 BytecodeNode node(Bytecode::kJumpIfUndefined, 0); 578 OutputJump(Bytecode::kJumpIfUndefined, label);
490 return OutputJump(&node, label); 579 return *this;
491 } 580 }
492 581
493 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( 582 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
494 BytecodeLabel* label) { 583 BytecodeLabel* label) {
495 BytecodeNode node(Bytecode::kJumpIfNotHole, 0); 584 OutputJump(Bytecode::kJumpIfNotHole, label);
496 return OutputJump(&node, label); 585 return *this;
497 } 586 }
498 587
499 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, 588 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label,
500 int loop_depth) { 589 int loop_depth) {
501 BytecodeNode node(Bytecode::kJumpLoop, 0, UnsignedOperand(loop_depth)); 590 OutputJump(Bytecode::kJumpLoop, UnsignedOperand(loop_depth), label);
502 return OutputJump(&node, label); 591 return *this;
503 } 592 }
504 593
505 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { 594 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
506 if (position != kNoSourcePosition) { 595 if (position != kNoSourcePosition) {
507 // We need to attach a non-breakable source position to a stack 596 // We need to attach a non-breakable source position to a stack
508 // check, so we simply add it as expression position. There can be 597 // check, so we simply add it as expression position. There can be
509 // a prior statement position from constructs like: 598 // a prior statement position from constructs like:
510 // 599 //
511 // do var x; while (false); 600 // do var x; while (false);
512 // 601 //
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 Return(); 702 Return();
614 } 703 }
615 DCHECK(return_seen_in_block_); 704 DCHECK(return_seen_in_block_);
616 } 705 }
617 706
618 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, 707 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
619 Register receiver_args, 708 Register receiver_args,
620 size_t receiver_args_count, 709 size_t receiver_args_count,
621 int feedback_slot, 710 int feedback_slot,
622 TailCallMode tail_call_mode) { 711 TailCallMode tail_call_mode) {
623 Bytecode bytecode = BytecodeForCall(tail_call_mode); 712 if (tail_call_mode == TailCallMode::kDisallow) {
624 Output(bytecode, RegisterOperand(callable), RegisterOperand(receiver_args), 713 Output(Bytecode::kCall, RegisterOperand(callable),
625 UnsignedOperand(receiver_args_count), UnsignedOperand(feedback_slot)); 714 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count),
715 UnsignedOperand(feedback_slot));
716 } else {
717 DCHECK(tail_call_mode == TailCallMode::kAllow);
718 Output(Bytecode::kTailCall, RegisterOperand(callable),
719 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count),
720 UnsignedOperand(feedback_slot));
721 }
626 return *this; 722 return *this;
627 } 723 }
628 724
629 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, 725 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
630 Register first_arg, 726 Register first_arg,
631 size_t arg_count, 727 size_t arg_count,
632 int feedback_slot_id) { 728 int feedback_slot_id) {
633 if (!first_arg.is_valid()) { 729 if (!first_arg.is_valid()) {
634 DCHECK_EQ(0u, arg_count); 730 DCHECK_EQ(0u, arg_count);
635 first_arg = Register(0); 731 first_arg = Register(0);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 774
679 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( 775 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(
680 int context_index, Register receiver_args, size_t receiver_args_count) { 776 int context_index, Register receiver_args, size_t receiver_args_count) {
681 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), 777 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index),
682 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count)); 778 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count));
683 return *this; 779 return *this;
684 } 780 }
685 781
686 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, 782 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
687 LanguageMode language_mode) { 783 LanguageMode language_mode) {
688 Output(BytecodeForDelete(language_mode), RegisterOperand(object)); 784 if (language_mode == SLOPPY) {
785 Output(Bytecode::kDeletePropertySloppy, RegisterOperand(object));
786 } else {
787 DCHECK_EQ(language_mode, STRICT);
788 Output(Bytecode::kDeletePropertyStrict, RegisterOperand(object));
789 }
689 return *this; 790 return *this;
690 } 791 }
691 792
692 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { 793 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) {
693 return constant_array_builder()->Insert(object); 794 return constant_array_builder()->Insert(object);
694 } 795 }
695 796
696 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { 797 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() {
697 return constant_array_builder()->AllocateEntry(); 798 return constant_array_builder()->AllocateEntry();
698 } 799 }
699 800
700 void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry, 801 void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry,
701 Handle<Object> object) { 802 Handle<Object> object) {
702 constant_array_builder()->InsertAllocatedEntry(entry, object); 803 constant_array_builder()->InsertAllocatedEntry(entry, object);
703 } 804 }
704 805
705 void BytecodeArrayBuilder::SetReturnPosition() { 806 void BytecodeArrayBuilder::SetReturnPosition() {
706 if (return_position_ == kNoSourcePosition) return; 807 if (return_position_ == kNoSourcePosition) return;
707 latest_source_info_.MakeStatementPosition(return_position_); 808 latest_source_info_.MakeStatementPosition(return_position_);
708 } 809 }
709 810
710 void BytecodeArrayBuilder::SetStatementPosition(Statement* stmt) {
711 if (stmt->position() == kNoSourcePosition) return;
712 latest_source_info_.MakeStatementPosition(stmt->position());
713 }
714
715 void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) {
716 if (expr->position() == kNoSourcePosition) return;
717 if (!latest_source_info_.is_statement()) {
718 // Ensure the current expression position is overwritten with the
719 // latest value.
720 latest_source_info_.MakeExpressionPosition(expr->position());
721 }
722 }
723
724 void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) {
725 if (expr->position() == kNoSourcePosition) return;
726 latest_source_info_.MakeStatementPosition(expr->position());
727 }
728
729 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { 811 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
730 return temporary_register_allocator()->RegisterIsLive(reg); 812 return temporary_register_allocator()->RegisterIsLive(reg);
731 } 813 }
732 814
733 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { 815 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
734 if (!reg.is_valid()) { 816 if (!reg.is_valid()) {
735 return false; 817 return false;
736 } 818 }
737 819
738 if (reg.is_current_context() || reg.is_function_closure() || 820 if (reg.is_current_context() || reg.is_function_closure() ||
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 } 864 }
783 break; 865 break;
784 case OperandType::kRuntimeId: 866 case OperandType::kRuntimeId:
785 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > 867 if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
786 OperandSize::kShort) { 868 OperandSize::kShort) {
787 return false; 869 return false;
788 } 870 }
789 break; 871 break;
790 case OperandType::kIdx: 872 case OperandType::kIdx:
791 // TODO(leszeks): Possibly split this up into constant pool indices and 873 // TODO(leszeks): Possibly split this up into constant pool indices and
792 // other indices, for checking 874 // other indices, for checking.
793 break; 875 break;
794 case OperandType::kUImm: 876 case OperandType::kUImm:
795 case OperandType::kImm: 877 case OperandType::kImm:
796 break; 878 break;
797 case OperandType::kMaybeReg: 879 case OperandType::kMaybeReg:
798 if (Register::FromOperand(operands[i]) == Register(0)) { 880 if (Register::FromOperand(operands[i]) == Register(0)) {
799 break; 881 break;
800 } 882 }
801 // Fall-through to kReg case. 883 // Fall-through to kReg case.
802 case OperandType::kReg: 884 case OperandType::kReg:
(...skipping 22 matching lines...) Expand all
825 return false; 907 return false;
826 } 908 }
827 break; 909 break;
828 } 910 }
829 } 911 }
830 } 912 }
831 913
832 return true; 914 return true;
833 } 915 }
834 916
835 // static
836 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
837 switch (op) {
838 case Token::Value::ADD:
839 return Bytecode::kAdd;
840 case Token::Value::SUB:
841 return Bytecode::kSub;
842 case Token::Value::MUL:
843 return Bytecode::kMul;
844 case Token::Value::DIV:
845 return Bytecode::kDiv;
846 case Token::Value::MOD:
847 return Bytecode::kMod;
848 case Token::Value::BIT_OR:
849 return Bytecode::kBitwiseOr;
850 case Token::Value::BIT_XOR:
851 return Bytecode::kBitwiseXor;
852 case Token::Value::BIT_AND:
853 return Bytecode::kBitwiseAnd;
854 case Token::Value::SHL:
855 return Bytecode::kShiftLeft;
856 case Token::Value::SAR:
857 return Bytecode::kShiftRight;
858 case Token::Value::SHR:
859 return Bytecode::kShiftRightLogical;
860 default:
861 UNREACHABLE();
862 return Bytecode::kIllegal;
863 }
864 }
865
866 // static
867 Bytecode BytecodeArrayBuilder::BytecodeForCountOperation(Token::Value op) {
868 switch (op) {
869 case Token::Value::ADD:
870 return Bytecode::kInc;
871 case Token::Value::SUB:
872 return Bytecode::kDec;
873 default:
874 UNREACHABLE();
875 return Bytecode::kIllegal;
876 }
877 }
878
879 // static
880 Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) {
881 switch (op) {
882 case Token::Value::EQ:
883 return Bytecode::kTestEqual;
884 case Token::Value::NE:
885 return Bytecode::kTestNotEqual;
886 case Token::Value::EQ_STRICT:
887 return Bytecode::kTestEqualStrict;
888 case Token::Value::LT:
889 return Bytecode::kTestLessThan;
890 case Token::Value::GT:
891 return Bytecode::kTestGreaterThan;
892 case Token::Value::LTE:
893 return Bytecode::kTestLessThanOrEqual;
894 case Token::Value::GTE:
895 return Bytecode::kTestGreaterThanOrEqual;
896 case Token::Value::INSTANCEOF:
897 return Bytecode::kTestInstanceOf;
898 case Token::Value::IN:
899 return Bytecode::kTestIn;
900 default:
901 UNREACHABLE();
902 return Bytecode::kIllegal;
903 }
904 }
905
906 // static
907 Bytecode BytecodeArrayBuilder::BytecodeForStoreNamedProperty(
908 LanguageMode language_mode) {
909 switch (language_mode) {
910 case SLOPPY:
911 return Bytecode::kStaNamedPropertySloppy;
912 case STRICT:
913 return Bytecode::kStaNamedPropertyStrict;
914 default:
915 UNREACHABLE();
916 }
917 return Bytecode::kIllegal;
918 }
919
920 // static
921 Bytecode BytecodeArrayBuilder::BytecodeForStoreKeyedProperty(
922 LanguageMode language_mode) {
923 switch (language_mode) {
924 case SLOPPY:
925 return Bytecode::kStaKeyedPropertySloppy;
926 case STRICT:
927 return Bytecode::kStaKeyedPropertyStrict;
928 default:
929 UNREACHABLE();
930 }
931 return Bytecode::kIllegal;
932 }
933
934 // static
935 Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(TypeofMode typeof_mode) {
936 return typeof_mode == INSIDE_TYPEOF ? Bytecode::kLdaGlobalInsideTypeof
937 : Bytecode::kLdaGlobal;
938 }
939
940 // static
941 Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal(
942 LanguageMode language_mode) {
943 switch (language_mode) {
944 case SLOPPY:
945 return Bytecode::kStaGlobalSloppy;
946 case STRICT:
947 return Bytecode::kStaGlobalStrict;
948 default:
949 UNREACHABLE();
950 }
951 return Bytecode::kIllegal;
952 }
953
954 // static
955 Bytecode BytecodeArrayBuilder::BytecodeForStoreLookupSlot(
956 LanguageMode language_mode) {
957 switch (language_mode) {
958 case SLOPPY:
959 return Bytecode::kStaLookupSlotSloppy;
960 case STRICT:
961 return Bytecode::kStaLookupSlotStrict;
962 default:
963 UNREACHABLE();
964 }
965 return Bytecode::kIllegal;
966 }
967
968 // static
969 Bytecode BytecodeArrayBuilder::BytecodeForCreateArguments(
970 CreateArgumentsType type) {
971 switch (type) {
972 case CreateArgumentsType::kMappedArguments:
973 return Bytecode::kCreateMappedArguments;
974 case CreateArgumentsType::kUnmappedArguments:
975 return Bytecode::kCreateUnmappedArguments;
976 case CreateArgumentsType::kRestParameter:
977 return Bytecode::kCreateRestParameter;
978 }
979 UNREACHABLE();
980 return Bytecode::kIllegal;
981 }
982
983 // static
984 Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) {
985 switch (language_mode) {
986 case SLOPPY:
987 return Bytecode::kDeletePropertySloppy;
988 case STRICT:
989 return Bytecode::kDeletePropertyStrict;
990 default:
991 UNREACHABLE();
992 }
993 return Bytecode::kIllegal;
994 }
995
996 // static
997 Bytecode BytecodeArrayBuilder::BytecodeForCall(TailCallMode tail_call_mode) {
998 switch (tail_call_mode) {
999 case TailCallMode::kDisallow:
1000 return Bytecode::kCall;
1001 case TailCallMode::kAllow:
1002 return Bytecode::kTailCall;
1003 default:
1004 UNREACHABLE();
1005 }
1006 return Bytecode::kIllegal;
1007 }
1008
1009 } // namespace interpreter 917 } // namespace interpreter
1010 } // namespace internal 918 } // namespace internal
1011 } // namespace v8 919 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698