OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/interpreter/bytecode-array-builder.h" | 7 #include "src/interpreter/bytecode-array-builder.h" |
8 #include "src/interpreter/bytecode-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
9 #include "test/unittests/test-utils.h" | 9 #include "test/unittests/test-utils.h" |
10 | 10 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
125 | 125 |
126 // Emit cast operator invocations. | 126 // Emit cast operator invocations. |
127 builder.CastAccumulatorToNumber() | 127 builder.CastAccumulatorToNumber() |
128 .CastAccumulatorToBoolean() | 128 .CastAccumulatorToBoolean() |
129 .CastAccumulatorToName(); | 129 .CastAccumulatorToName(); |
130 | 130 |
131 // Emit control flow. Return must be the last instruction. | 131 // Emit control flow. Return must be the last instruction. |
132 BytecodeLabel start; | 132 BytecodeLabel start; |
133 builder.Bind(&start); | 133 builder.Bind(&start); |
134 // Short jumps with Imm8 operands | 134 // Short jumps with Imm8 operands |
135 builder.Jump(&start) | 135 builder.Jump(&start); |
136 // Perform an operation that returns boolean value to | |
137 // generate JumpIfTrue/False | |
138 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | |
136 .JumpIfTrue(&start) | 139 .JumpIfTrue(&start) |
137 .JumpIfFalse(&start) | 140 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
138 .JumpIfToBooleanTrue(&start) | 141 .JumpIfFalse(&start); |
139 .JumpIfToBooleanFalse(&start); | 142 // Perform an operation that returns a non-boolean operation to |
143 // generate JumpIfToBooleanTrue/False. | |
144 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | |
145 .JumpIfTrue(&start) | |
146 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | |
147 .JumpIfFalse(&start); | |
140 // Insert dummy ops to force longer jumps | 148 // Insert dummy ops to force longer jumps |
141 for (int i = 0; i < 128; i++) { | 149 for (int i = 0; i < 128; i++) { |
142 builder.LoadTrue(); | 150 builder.LoadTrue(); |
143 } | 151 } |
144 // Longer jumps requiring Constant operand | 152 // Longer jumps requiring Constant operand |
145 builder.Jump(&start) | 153 builder.Jump(&start); |
154 // Perform an operation that returns boolean value to | |
155 // generate JumpIfTrue/False | |
156 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | |
146 .JumpIfTrue(&start) | 157 .JumpIfTrue(&start) |
147 .JumpIfFalse(&start) | 158 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
148 .JumpIfToBooleanTrue(&start) | 159 .JumpIfFalse(&start); |
149 .JumpIfToBooleanFalse(&start); | 160 // Perform an operation that returns a non-boolean operation to |
161 // generate JumpIfToBooleanTrue/False. | |
162 builder.JumpIfTrue(&start).JumpIfFalse(&start); | |
150 | 163 |
151 builder.EnterBlock() | 164 builder.EnterBlock() |
152 .Throw() | 165 .Throw() |
153 .LeaveBlock(); | 166 .LeaveBlock(); |
154 | 167 |
155 builder.Return(); | 168 builder.Return(); |
156 | 169 |
157 // Generate BytecodeArray. | 170 // Generate BytecodeArray. |
158 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); | 171 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); |
159 CHECK_EQ(the_array->frame_size(), | 172 CHECK_EQ(the_array->frame_size(), |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
307 // Should only have one entry for each identical constant. | 320 // Should only have one entry for each identical constant. |
308 CHECK_EQ(array->constant_pool()->length(), 3); | 321 CHECK_EQ(array->constant_pool()->length(), 3); |
309 } | 322 } |
310 | 323 |
311 | 324 |
312 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { | 325 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { |
313 static const int kFarJumpDistance = 256; | 326 static const int kFarJumpDistance = 256; |
314 | 327 |
315 BytecodeArrayBuilder builder(isolate(), zone()); | 328 BytecodeArrayBuilder builder(isolate(), zone()); |
316 builder.set_parameter_count(0); | 329 builder.set_parameter_count(0); |
317 builder.set_locals_count(0); | 330 builder.set_locals_count(1); |
318 builder.set_context_count(0); | 331 builder.set_context_count(0); |
319 | 332 |
320 BytecodeLabel far0, far1, far2; | 333 Register reg(0); |
321 BytecodeLabel near0, near1, near2; | 334 BytecodeLabel far0, far1, far2, far3, far4; |
335 BytecodeLabel near0, near1, near2, near3, near4; | |
322 | 336 |
323 builder.Jump(&near0) | 337 builder.Jump(&near0) |
338 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | |
324 .JumpIfTrue(&near1) | 339 .JumpIfTrue(&near1) |
340 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | |
325 .JumpIfFalse(&near2) | 341 .JumpIfFalse(&near2) |
342 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | |
343 .JumpIfTrue(&near3) | |
344 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | |
345 .JumpIfFalse(&near4) | |
326 .Bind(&near0) | 346 .Bind(&near0) |
327 .Bind(&near1) | 347 .Bind(&near1) |
328 .Bind(&near2) | 348 .Bind(&near2) |
349 .Bind(&near3) | |
350 .Bind(&near4) | |
329 .Jump(&far0) | 351 .Jump(&far0) |
352 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | |
330 .JumpIfTrue(&far1) | 353 .JumpIfTrue(&far1) |
331 .JumpIfFalse(&far2); | 354 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
332 for (int i = 0; i < kFarJumpDistance - 6; i++) { | 355 .JumpIfFalse(&far2) |
356 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | |
357 .JumpIfTrue(&far3) | |
358 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | |
359 .JumpIfFalse(&far4); | |
360 for (int i = 0; i < kFarJumpDistance - 18; i++) { | |
333 builder.LoadUndefined(); | 361 builder.LoadUndefined(); |
334 } | 362 } |
335 builder.Bind(&far0).Bind(&far1).Bind(&far2); | 363 builder.Bind(&far0).Bind(&far1).Bind(&far2).Bind(&far3).Bind(&far4); |
336 builder.Return(); | 364 builder.Return(); |
337 | 365 |
338 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 366 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
339 DCHECK_EQ(array->length(), 12 + kFarJumpDistance - 6 + 1); | 367 DCHECK_EQ(array->length(), 36 + kFarJumpDistance - 18 + 1); |
340 | 368 |
341 BytecodeArrayIterator iterator(array); | 369 BytecodeArrayIterator iterator(array); |
342 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 370 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
371 CHECK_EQ(iterator.GetImmediateOperand(0), 18); | |
372 iterator.Advance(); | |
373 | |
374 // ignore compare operation | |
rmcilroy
2015/10/29 10:40:24
nit - capital letter and full stop (throughout)
mythria
2015/10/29 17:58:39
Done.
| |
375 iterator.Advance(); | |
376 | |
377 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); | |
378 CHECK_EQ(iterator.GetImmediateOperand(0), 14); | |
379 iterator.Advance(); | |
380 | |
381 // ignore compare operation | |
382 iterator.Advance(); | |
383 | |
384 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); | |
385 CHECK_EQ(iterator.GetImmediateOperand(0), 10); | |
386 iterator.Advance(); | |
387 | |
388 // ignore add operation | |
389 iterator.Advance(); | |
390 | |
391 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); | |
343 CHECK_EQ(iterator.GetImmediateOperand(0), 6); | 392 CHECK_EQ(iterator.GetImmediateOperand(0), 6); |
344 iterator.Advance(); | 393 iterator.Advance(); |
345 | 394 |
346 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); | 395 // ignore add operation |
347 CHECK_EQ(iterator.GetImmediateOperand(0), 4); | |
348 iterator.Advance(); | 396 iterator.Advance(); |
349 | 397 |
350 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); | 398 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse); |
351 CHECK_EQ(iterator.GetImmediateOperand(0), 2); | 399 CHECK_EQ(iterator.GetImmediateOperand(0), 2); |
352 iterator.Advance(); | 400 iterator.Advance(); |
353 | 401 |
402 | |
354 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); | 403 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); |
355 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 404 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
356 Smi::FromInt(kFarJumpDistance)); | 405 Smi::FromInt(kFarJumpDistance)); |
357 CHECK_EQ( | 406 CHECK_EQ( |
358 array->get(iterator.current_offset() + | 407 array->get(iterator.current_offset() + |
359 Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()), | 408 Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()), |
360 Bytecodes::ToByte(Bytecode::kReturn)); | 409 Bytecodes::ToByte(Bytecode::kReturn)); |
361 iterator.Advance(); | 410 iterator.Advance(); |
362 | 411 |
412 // ignore compare operation | |
413 iterator.Advance(); | |
414 | |
363 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); | 415 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); |
364 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 416 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
365 Smi::FromInt(kFarJumpDistance - 2)); | 417 Smi::FromInt(kFarJumpDistance - 4)); |
366 CHECK_EQ( | 418 CHECK_EQ( |
367 array->get(iterator.current_offset() + | 419 array->get(iterator.current_offset() + |
368 Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()), | 420 Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()), |
369 Bytecodes::ToByte(Bytecode::kReturn)); | 421 Bytecodes::ToByte(Bytecode::kReturn)); |
370 iterator.Advance(); | 422 iterator.Advance(); |
371 | 423 |
424 // ignore compare operation | |
425 iterator.Advance(); | |
426 | |
372 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); | 427 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); |
373 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 428 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
374 Smi::FromInt(kFarJumpDistance - 4)); | 429 Smi::FromInt(kFarJumpDistance - 8)); |
375 CHECK_EQ( | 430 CHECK_EQ( |
376 array->get(iterator.current_offset() + | 431 array->get(iterator.current_offset() + |
377 Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()), | 432 Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()), |
433 Bytecodes::ToByte(Bytecode::kReturn)); | |
434 iterator.Advance(); | |
435 | |
436 // ignore add operation | |
437 iterator.Advance(); | |
438 | |
439 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant); | |
440 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | |
441 Smi::FromInt(kFarJumpDistance - 12)); | |
442 CHECK_EQ( | |
443 array->get(iterator.current_offset() + | |
444 Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()), | |
445 Bytecodes::ToByte(Bytecode::kReturn)); | |
446 iterator.Advance(); | |
447 | |
448 // ignore add operation | |
449 iterator.Advance(); | |
450 | |
451 CHECK_EQ(iterator.current_bytecode(), | |
452 Bytecode::kJumpIfToBooleanFalseConstant); | |
453 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | |
454 Smi::FromInt(kFarJumpDistance - 16)); | |
455 CHECK_EQ( | |
456 array->get(iterator.current_offset() + | |
457 Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()), | |
378 Bytecodes::ToByte(Bytecode::kReturn)); | 458 Bytecodes::ToByte(Bytecode::kReturn)); |
379 iterator.Advance(); | 459 iterator.Advance(); |
380 } | 460 } |
381 | 461 |
382 | 462 |
383 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { | 463 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { |
384 BytecodeArrayBuilder builder(isolate(), zone()); | 464 BytecodeArrayBuilder builder(isolate(), zone()); |
385 builder.set_parameter_count(0); | 465 builder.set_parameter_count(0); |
386 builder.set_locals_count(0); | 466 builder.set_locals_count(1); |
387 builder.set_context_count(0); | 467 builder.set_context_count(0); |
468 Register reg(0); | |
388 | 469 |
389 BytecodeLabel label0, label1, label2; | 470 BytecodeLabel label0, label1, label2, label3, label4; |
390 builder.Bind(&label0) | 471 builder.Bind(&label0) |
391 .Jump(&label0) | 472 .Jump(&label0) |
473 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | |
392 .Bind(&label1) | 474 .Bind(&label1) |
393 .JumpIfTrue(&label1) | 475 .JumpIfTrue(&label1) |
476 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | |
394 .Bind(&label2) | 477 .Bind(&label2) |
478 .JumpIfFalse(&label2) | |
479 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | |
480 .Bind(&label3) | |
481 .JumpIfTrue(&label3) | |
482 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | |
483 .Bind(&label4) | |
484 .JumpIfFalse(&label4); | |
485 for (int i = 0; i < 64; i++) { | |
486 builder.Jump(&label4); | |
487 } | |
488 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | |
489 .JumpIfFalse(&label4); | |
490 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | |
491 .JumpIfTrue(&label3); | |
492 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | |
395 .JumpIfFalse(&label2); | 493 .JumpIfFalse(&label2); |
396 for (int i = 0; i < 64; i++) { | 494 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
397 builder.Jump(&label2); | 495 .JumpIfTrue(&label1); |
398 } | |
399 builder.JumpIfFalse(&label2); | |
400 builder.JumpIfTrue(&label1); | |
401 builder.Jump(&label0); | 496 builder.Jump(&label0); |
402 builder.Return(); | 497 builder.Return(); |
403 | 498 |
404 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 499 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
405 BytecodeArrayIterator iterator(array); | 500 BytecodeArrayIterator iterator(array); |
406 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 501 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
407 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 502 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
408 iterator.Advance(); | 503 iterator.Advance(); |
504 // ignore compare operation | |
505 iterator.Advance(); | |
409 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); | 506 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); |
410 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 507 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
411 iterator.Advance(); | 508 iterator.Advance(); |
509 // ignore compare operation | |
510 iterator.Advance(); | |
412 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); | 511 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); |
413 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 512 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
414 iterator.Advance(); | 513 iterator.Advance(); |
514 // ignore binary operation | |
515 iterator.Advance(); | |
516 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); | |
517 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | |
518 iterator.Advance(); | |
519 // ignore binary operation | |
520 iterator.Advance(); | |
521 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse); | |
522 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | |
523 iterator.Advance(); | |
415 for (int i = 0; i < 64; i++) { | 524 for (int i = 0; i < 64; i++) { |
416 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 525 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
417 CHECK_EQ(iterator.GetImmediateOperand(0), -i * 2 - 2); | 526 CHECK_EQ(iterator.GetImmediateOperand(0), -i * 2 - 2); |
418 iterator.Advance(); | 527 iterator.Advance(); |
419 } | 528 } |
529 // ignore binary operation | |
530 iterator.Advance(); | |
531 CHECK_EQ(iterator.current_bytecode(), | |
532 Bytecode::kJumpIfToBooleanFalseConstant); | |
533 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -132); | |
534 iterator.Advance(); | |
535 // ignore binary operation | |
536 iterator.Advance(); | |
537 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant); | |
538 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -140); | |
539 iterator.Advance(); | |
540 // ignore compare operation | |
541 iterator.Advance(); | |
420 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); | 542 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); |
421 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -130); | 543 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -148); |
544 iterator.Advance(); | |
545 // ignore compare operation | |
422 iterator.Advance(); | 546 iterator.Advance(); |
423 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); | 547 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); |
424 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -134); | 548 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -156); |
425 iterator.Advance(); | 549 iterator.Advance(); |
426 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); | 550 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); |
427 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -138); | 551 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -162); |
428 iterator.Advance(); | 552 iterator.Advance(); |
429 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 553 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
430 iterator.Advance(); | 554 iterator.Advance(); |
431 CHECK(iterator.done()); | 555 CHECK(iterator.done()); |
432 } | 556 } |
433 | 557 |
434 | 558 |
435 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { | 559 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { |
436 BytecodeArrayBuilder builder(isolate(), zone()); | 560 BytecodeArrayBuilder builder(isolate(), zone()); |
437 builder.set_parameter_count(0); | 561 builder.set_parameter_count(0); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
539 | 663 |
540 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 664 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
541 iterator.Advance(); | 665 iterator.Advance(); |
542 CHECK(iterator.done()); | 666 CHECK(iterator.done()); |
543 } | 667 } |
544 | 668 |
545 | 669 |
546 } // namespace interpreter | 670 } // namespace interpreter |
547 } // namespace internal | 671 } // namespace internal |
548 } // namespace v8 | 672 } // namespace v8 |
OLD | NEW |