LCOV - code coverage report
Current view: top level - test/unittests/interpreter - bytecode-array-builder-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 512 512 100.0 %
Date: 2019-01-20 Functions: 24 37 64.9 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include <limits>
       6             : 
       7             : #include "src/v8.h"
       8             : 
       9             : #include "src/ast/scopes.h"
      10             : #include "src/interpreter/bytecode-array-builder.h"
      11             : #include "src/interpreter/bytecode-array-iterator.h"
      12             : #include "src/interpreter/bytecode-jump-table.h"
      13             : #include "src/interpreter/bytecode-label.h"
      14             : #include "src/interpreter/bytecode-register-allocator.h"
      15             : #include "src/objects-inl.h"
      16             : #include "src/objects/smi.h"
      17             : #include "test/unittests/interpreter/bytecode-utils.h"
      18             : #include "test/unittests/test-utils.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : namespace interpreter {
      23             : 
      24             : class BytecodeArrayBuilderTest : public TestWithIsolateAndZone {
      25             :  public:
      26          11 :   BytecodeArrayBuilderTest() = default;
      27          11 :   ~BytecodeArrayBuilderTest() override = default;
      28             : };
      29             : 
      30             : using ToBooleanMode = BytecodeArrayBuilder::ToBooleanMode;
      31             : 
      32       15129 : TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
      33           1 :   FeedbackVectorSpec feedback_spec(zone());
      34           2 :   BytecodeArrayBuilder builder(zone(), 1, 131, &feedback_spec);
      35             :   Factory* factory = isolate()->factory();
      36             :   AstValueFactory ast_factory(zone(), isolate()->ast_string_constants(),
      37           2 :                               isolate()->heap()->HashSeed());
      38           1 :   DeclarationScope scope(zone(), &ast_factory);
      39             : 
      40           1 :   CHECK_EQ(builder.locals_count(), 131);
      41           1 :   CHECK_EQ(builder.fixed_register_count(), 131);
      42             : 
      43             :   Register reg(0);
      44             :   Register other(reg.index() + 1);
      45             :   Register wide(128);
      46             :   RegisterList empty;
      47           1 :   RegisterList single = BytecodeUtils::NewRegisterList(0, 1);
      48           1 :   RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
      49           1 :   RegisterList triple = BytecodeUtils::NewRegisterList(0, 3);
      50           1 :   RegisterList reg_list = BytecodeUtils::NewRegisterList(0, 10);
      51             : 
      52             :   // Emit argument creation operations.
      53           1 :   builder.CreateArguments(CreateArgumentsType::kMappedArguments)
      54           1 :       .CreateArguments(CreateArgumentsType::kUnmappedArguments)
      55           1 :       .CreateArguments(CreateArgumentsType::kRestParameter);
      56             : 
      57             :   // Emit constant loads.
      58           1 :   builder.LoadLiteral(Smi::zero())
      59           1 :       .StoreAccumulatorInRegister(reg)
      60           1 :       .LoadLiteral(Smi::FromInt(8))
      61             :       .CompareOperation(Token::Value::EQ, reg,
      62           1 :                         1)  // Prevent peephole optimization
      63             :                             // LdaSmi, Star -> LdrSmi.
      64           1 :       .StoreAccumulatorInRegister(reg)
      65           1 :       .LoadLiteral(Smi::FromInt(10000000))
      66           1 :       .StoreAccumulatorInRegister(reg)
      67           2 :       .LoadLiteral(ast_factory.GetOneByteString("A constant"))
      68           1 :       .StoreAccumulatorInRegister(reg)
      69           1 :       .LoadUndefined()
      70           1 :       .StoreAccumulatorInRegister(reg)
      71           1 :       .LoadNull()
      72           1 :       .StoreAccumulatorInRegister(reg)
      73           1 :       .LoadTheHole()
      74           1 :       .StoreAccumulatorInRegister(reg)
      75           1 :       .LoadTrue()
      76           1 :       .StoreAccumulatorInRegister(reg)
      77           1 :       .LoadFalse()
      78           1 :       .StoreAccumulatorInRegister(wide);
      79             : 
      80             :   // Emit Ldar and Star taking care to foil the register optimizer.
      81           1 :   builder.StackCheck(0)
      82           1 :       .LoadAccumulatorWithRegister(other)
      83           1 :       .BinaryOperation(Token::ADD, reg, 1)
      84           1 :       .StoreAccumulatorInRegister(reg)
      85           1 :       .LoadNull();
      86             : 
      87             :   // Emit register-register transfer.
      88           1 :   builder.MoveRegister(reg, other);
      89           1 :   builder.MoveRegister(reg, wide);
      90             : 
      91             :   FeedbackSlot load_global_slot =
      92             :       feedback_spec.AddLoadGlobalICSlot(NOT_INSIDE_TYPEOF);
      93             :   FeedbackSlot load_global_typeof_slot =
      94             :       feedback_spec.AddLoadGlobalICSlot(INSIDE_TYPEOF);
      95             :   FeedbackSlot sloppy_store_global_slot =
      96             :       feedback_spec.AddStoreGlobalICSlot(LanguageMode::kSloppy);
      97             :   FeedbackSlot load_slot = feedback_spec.AddLoadICSlot();
      98             :   FeedbackSlot keyed_load_slot = feedback_spec.AddKeyedLoadICSlot();
      99             :   FeedbackSlot sloppy_store_slot =
     100             :       feedback_spec.AddStoreICSlot(LanguageMode::kSloppy);
     101             :   FeedbackSlot strict_store_slot =
     102             :       feedback_spec.AddStoreICSlot(LanguageMode::kStrict);
     103             :   FeedbackSlot sloppy_keyed_store_slot =
     104             :       feedback_spec.AddKeyedStoreICSlot(LanguageMode::kSloppy);
     105             :   FeedbackSlot strict_keyed_store_slot =
     106             :       feedback_spec.AddKeyedStoreICSlot(LanguageMode::kStrict);
     107             :   FeedbackSlot store_own_slot = feedback_spec.AddStoreOwnICSlot();
     108             :   FeedbackSlot store_array_element_slot =
     109             :       feedback_spec.AddStoreInArrayLiteralICSlot();
     110             : 
     111             :   // Emit global load / store operations.
     112           1 :   const AstRawString* name = ast_factory.GetOneByteString("var_name");
     113             :   builder
     114           1 :       .LoadGlobal(name, load_global_slot.ToInt(), TypeofMode::NOT_INSIDE_TYPEOF)
     115             :       .LoadGlobal(name, load_global_typeof_slot.ToInt(),
     116           1 :                   TypeofMode::INSIDE_TYPEOF)
     117           1 :       .StoreGlobal(name, sloppy_store_global_slot.ToInt());
     118             : 
     119             :   // Emit context operations.
     120           1 :   builder.PushContext(reg)
     121           1 :       .PopContext(reg)
     122           1 :       .LoadContextSlot(reg, 1, 0, BytecodeArrayBuilder::kMutableSlot)
     123           1 :       .StoreContextSlot(reg, 1, 0)
     124           1 :       .LoadContextSlot(reg, 2, 0, BytecodeArrayBuilder::kImmutableSlot)
     125           1 :       .StoreContextSlot(reg, 3, 0);
     126             : 
     127             :   // Emit context operations which operate on the local context.
     128             :   builder
     129             :       .LoadContextSlot(Register::current_context(), 1, 0,
     130           1 :                        BytecodeArrayBuilder::kMutableSlot)
     131           2 :       .StoreContextSlot(Register::current_context(), 1, 0)
     132             :       .LoadContextSlot(Register::current_context(), 2, 0,
     133           2 :                        BytecodeArrayBuilder::kImmutableSlot)
     134           2 :       .StoreContextSlot(Register::current_context(), 3, 0);
     135             : 
     136             :   // Emit load / store property operations.
     137           1 :   builder.LoadNamedProperty(reg, name, load_slot.ToInt())
     138           1 :       .LoadNamedPropertyNoFeedback(reg, name)
     139           1 :       .LoadKeyedProperty(reg, keyed_load_slot.ToInt())
     140             :       .StoreNamedProperty(reg, name, sloppy_store_slot.ToInt(),
     141           1 :                           LanguageMode::kSloppy)
     142           1 :       .StoreNamedPropertyNoFeedback(reg, name, LanguageMode::kStrict)
     143           1 :       .StoreNamedPropertyNoFeedback(reg, name, LanguageMode::kSloppy)
     144             :       .StoreKeyedProperty(reg, reg, sloppy_keyed_store_slot.ToInt(),
     145           1 :                           LanguageMode::kSloppy)
     146             :       .StoreNamedProperty(reg, name, strict_store_slot.ToInt(),
     147           1 :                           LanguageMode::kStrict)
     148             :       .StoreKeyedProperty(reg, reg, strict_keyed_store_slot.ToInt(),
     149           1 :                           LanguageMode::kStrict)
     150           1 :       .StoreNamedOwnProperty(reg, name, store_own_slot.ToInt())
     151           1 :       .StoreInArrayLiteral(reg, reg, store_array_element_slot.ToInt());
     152             : 
     153             :   // Emit load / store lookup slots.
     154           1 :   builder.LoadLookupSlot(name, TypeofMode::NOT_INSIDE_TYPEOF)
     155           1 :       .LoadLookupSlot(name, TypeofMode::INSIDE_TYPEOF)
     156           1 :       .StoreLookupSlot(name, LanguageMode::kSloppy, LookupHoistingMode::kNormal)
     157             :       .StoreLookupSlot(name, LanguageMode::kSloppy,
     158           1 :                        LookupHoistingMode::kLegacySloppy)
     159             :       .StoreLookupSlot(name, LanguageMode::kStrict,
     160           1 :                        LookupHoistingMode::kNormal);
     161             : 
     162             :   // Emit load / store lookup slots with context fast paths.
     163           1 :   builder.LoadLookupContextSlot(name, TypeofMode::NOT_INSIDE_TYPEOF, 1, 0)
     164           1 :       .LoadLookupContextSlot(name, TypeofMode::INSIDE_TYPEOF, 1, 0);
     165             : 
     166             :   // Emit load / store lookup slots with global fast paths.
     167           1 :   builder.LoadLookupGlobalSlot(name, TypeofMode::NOT_INSIDE_TYPEOF, 1, 0)
     168           1 :       .LoadLookupGlobalSlot(name, TypeofMode::INSIDE_TYPEOF, 1, 0);
     169             : 
     170             :   // Emit closure operations.
     171           1 :   builder.CreateClosure(0, 1, NOT_TENURED);
     172             : 
     173             :   // Emit create context operation.
     174           1 :   builder.CreateBlockContext(&scope);
     175           1 :   builder.CreateCatchContext(reg, &scope);
     176           1 :   builder.CreateFunctionContext(&scope, 1);
     177           1 :   builder.CreateEvalContext(&scope, 1);
     178           1 :   builder.CreateWithContext(reg, &scope);
     179             : 
     180             :   // Emit literal creation operations.
     181           1 :   builder.CreateRegExpLiteral(ast_factory.GetOneByteString("a"), 0, 0);
     182           1 :   builder.CreateArrayLiteral(0, 0, 0);
     183           1 :   builder.CreateObjectLiteral(0, 0, 0);
     184             : 
     185             :   // Emit tagged template operations.
     186           1 :   builder.GetTemplateObject(0, 0);
     187             : 
     188             :   // Call operations.
     189           1 :   builder.CallAnyReceiver(reg, reg_list, 1)
     190           1 :       .CallProperty(reg, reg_list, 1)
     191           1 :       .CallProperty(reg, single, 1)
     192           1 :       .CallProperty(reg, pair, 1)
     193           1 :       .CallProperty(reg, triple, 1)
     194           1 :       .CallUndefinedReceiver(reg, reg_list, 1)
     195           1 :       .CallUndefinedReceiver(reg, empty, 1)
     196           1 :       .CallUndefinedReceiver(reg, single, 1)
     197           1 :       .CallUndefinedReceiver(reg, pair, 1)
     198           1 :       .CallRuntime(Runtime::kIsArray, reg)
     199           1 :       .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg_list, pair)
     200           1 :       .CallJSRuntime(Context::OBJECT_CREATE, reg_list)
     201           1 :       .CallWithSpread(reg, reg_list, 1)
     202           1 :       .CallNoFeedback(reg, reg_list);
     203             : 
     204             :   // Emit binary operator invocations.
     205           1 :   builder.BinaryOperation(Token::Value::ADD, reg, 1)
     206           1 :       .BinaryOperation(Token::Value::SUB, reg, 2)
     207           1 :       .BinaryOperation(Token::Value::MUL, reg, 3)
     208           1 :       .BinaryOperation(Token::Value::DIV, reg, 4)
     209           1 :       .BinaryOperation(Token::Value::MOD, reg, 5)
     210           1 :       .BinaryOperation(Token::Value::EXP, reg, 6);
     211             : 
     212             :   // Emit bitwise operator invocations
     213           1 :   builder.BinaryOperation(Token::Value::BIT_OR, reg, 6)
     214           1 :       .BinaryOperation(Token::Value::BIT_XOR, reg, 7)
     215           1 :       .BinaryOperation(Token::Value::BIT_AND, reg, 8);
     216             : 
     217             :   // Emit shift operator invocations
     218           1 :   builder.BinaryOperation(Token::Value::SHL, reg, 9)
     219           1 :       .BinaryOperation(Token::Value::SAR, reg, 10)
     220           1 :       .BinaryOperation(Token::Value::SHR, reg, 11);
     221             : 
     222             :   // Emit Smi binary operations.
     223           1 :   builder.BinaryOperationSmiLiteral(Token::Value::ADD, Smi::FromInt(42), 2)
     224           1 :       .BinaryOperationSmiLiteral(Token::Value::SUB, Smi::FromInt(42), 2)
     225           1 :       .BinaryOperationSmiLiteral(Token::Value::MUL, Smi::FromInt(42), 2)
     226           1 :       .BinaryOperationSmiLiteral(Token::Value::DIV, Smi::FromInt(42), 2)
     227           1 :       .BinaryOperationSmiLiteral(Token::Value::MOD, Smi::FromInt(42), 2)
     228           1 :       .BinaryOperationSmiLiteral(Token::Value::EXP, Smi::FromInt(42), 2)
     229           1 :       .BinaryOperationSmiLiteral(Token::Value::BIT_OR, Smi::FromInt(42), 2)
     230           1 :       .BinaryOperationSmiLiteral(Token::Value::BIT_XOR, Smi::FromInt(42), 2)
     231           1 :       .BinaryOperationSmiLiteral(Token::Value::BIT_AND, Smi::FromInt(42), 2)
     232           1 :       .BinaryOperationSmiLiteral(Token::Value::SHL, Smi::FromInt(42), 2)
     233           1 :       .BinaryOperationSmiLiteral(Token::Value::SAR, Smi::FromInt(42), 2)
     234           1 :       .BinaryOperationSmiLiteral(Token::Value::SHR, Smi::FromInt(42), 2);
     235             : 
     236             :   // Emit unary and count operator invocations.
     237           1 :   builder.UnaryOperation(Token::Value::INC, 1)
     238           1 :       .UnaryOperation(Token::Value::DEC, 1)
     239           1 :       .UnaryOperation(Token::Value::ADD, 1)
     240           1 :       .UnaryOperation(Token::Value::SUB, 1)
     241           1 :       .UnaryOperation(Token::Value::BIT_NOT, 1);
     242             : 
     243             :   // Emit unary operator invocations.
     244           1 :   builder.LogicalNot(ToBooleanMode::kConvertToBoolean)
     245           1 :       .LogicalNot(ToBooleanMode::kAlreadyBoolean)
     246           1 :       .TypeOf();
     247             : 
     248             :   // Emit delete
     249           1 :   builder.Delete(reg, LanguageMode::kSloppy).Delete(reg, LanguageMode::kStrict);
     250             : 
     251             :   // Emit construct.
     252           1 :   builder.Construct(reg, reg_list, 1).ConstructWithSpread(reg, reg_list, 1);
     253             : 
     254             :   // Emit test operator invocations.
     255           1 :   builder.CompareOperation(Token::Value::EQ, reg, 1)
     256           1 :       .CompareOperation(Token::Value::EQ_STRICT, reg, 2)
     257           1 :       .CompareOperation(Token::Value::LT, reg, 3)
     258           1 :       .CompareOperation(Token::Value::GT, reg, 4)
     259           1 :       .CompareOperation(Token::Value::LTE, reg, 5)
     260           1 :       .CompareOperation(Token::Value::GTE, reg, 6)
     261           1 :       .CompareTypeOf(TestTypeOfFlags::LiteralFlag::kNumber)
     262           1 :       .CompareOperation(Token::Value::INSTANCEOF, reg, 7)
     263           1 :       .CompareOperation(Token::Value::IN, reg)
     264           1 :       .CompareReference(reg)
     265           1 :       .CompareUndetectable()
     266           1 :       .CompareUndefined()
     267           1 :       .CompareNull();
     268             : 
     269             :   // Emit conversion operator invocations.
     270           1 :   builder.ToNumber(1).ToNumeric(1).ToObject(reg).ToName(reg).ToString();
     271             : 
     272             :   // Emit GetSuperConstructor.
     273           1 :   builder.GetSuperConstructor(reg);
     274             : 
     275             :   // Hole checks.
     276           1 :   builder.ThrowReferenceErrorIfHole(name)
     277           1 :       .ThrowSuperAlreadyCalledIfNotHole()
     278           1 :       .ThrowSuperNotCalledIfHole();
     279             : 
     280             :   // Short jumps with Imm8 operands
     281             :   {
     282             :     BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4,
     283             :         after_jump5, after_jump6, after_jump7, after_jump8, after_jump9,
     284             :         after_jump10;
     285           1 :     builder.Bind(&start)
     286           1 :         .Jump(&after_jump1)
     287           1 :         .Bind(&after_jump1)
     288           1 :         .JumpIfNull(&after_jump2)
     289           1 :         .Bind(&after_jump2)
     290           1 :         .JumpIfNotNull(&after_jump3)
     291           1 :         .Bind(&after_jump3)
     292           1 :         .JumpIfUndefined(&after_jump4)
     293           1 :         .Bind(&after_jump4)
     294           1 :         .JumpIfNotUndefined(&after_jump5)
     295           1 :         .Bind(&after_jump5)
     296           1 :         .JumpIfJSReceiver(&after_jump6)
     297           1 :         .Bind(&after_jump6)
     298           1 :         .JumpIfTrue(ToBooleanMode::kConvertToBoolean, &after_jump7)
     299           1 :         .Bind(&after_jump7)
     300           1 :         .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &after_jump8)
     301           1 :         .Bind(&after_jump8)
     302           1 :         .JumpIfFalse(ToBooleanMode::kConvertToBoolean, &after_jump9)
     303           1 :         .Bind(&after_jump9)
     304           1 :         .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &after_jump10)
     305           1 :         .Bind(&after_jump10)
     306           1 :         .JumpLoop(&start, 0);
     307             :   }
     308             : 
     309             :   // Longer jumps with constant operands
     310          11 :   BytecodeLabel end[10];
     311             :   {
     312             :     BytecodeLabel after_jump;
     313           1 :     builder.Jump(&end[0])
     314           1 :         .Bind(&after_jump)
     315           1 :         .JumpIfTrue(ToBooleanMode::kConvertToBoolean, &end[1])
     316           1 :         .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &end[2])
     317           1 :         .JumpIfFalse(ToBooleanMode::kConvertToBoolean, &end[3])
     318           1 :         .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &end[4])
     319           1 :         .JumpIfNull(&end[5])
     320           1 :         .JumpIfNotNull(&end[6])
     321           1 :         .JumpIfUndefined(&end[7])
     322           1 :         .JumpIfNotUndefined(&end[8])
     323           2 :         .LoadLiteral(ast_factory.prototype_string())
     324           1 :         .JumpIfJSReceiver(&end[9]);
     325             :   }
     326             : 
     327             :   // Emit Smi table switch bytecode.
     328           1 :   BytecodeJumpTable* jump_table = builder.AllocateJumpTable(1, 0);
     329           1 :   builder.SwitchOnSmiNoFeedback(jump_table).Bind(jump_table, 0);
     330             : 
     331             :   // Emit set pending message bytecode.
     332           1 :   builder.SetPendingMessage();
     333             : 
     334             :   // Emit stack check bytecode.
     335           1 :   builder.StackCheck(0);
     336             : 
     337             :   // Emit throw and re-throw in it's own basic block so that the rest of the
     338             :   // code isn't omitted due to being dead.
     339             :   BytecodeLabel after_throw;
     340           1 :   builder.Throw().Bind(&after_throw);
     341             :   BytecodeLabel after_rethrow;
     342           1 :   builder.ReThrow().Bind(&after_rethrow);
     343             : 
     344           1 :   builder.ForInEnumerate(reg)
     345           1 :       .ForInPrepare(triple, 1)
     346           1 :       .ForInContinue(reg, reg)
     347           1 :       .ForInNext(reg, reg, pair, 1)
     348           1 :       .ForInStep(reg);
     349             : 
     350             :   // Wide constant pool loads
     351         257 :   for (int i = 0; i < 256; i++) {
     352             :     // Emit junk in constant pool to force wide constant pool index.
     353         256 :     builder.LoadLiteral(2.5321 + i);
     354             :   }
     355           1 :   builder.LoadLiteral(Smi::FromInt(20000000));
     356           1 :   const AstRawString* wide_name = ast_factory.GetOneByteString("var_wide_name");
     357             : 
     358             :   builder.StoreDataPropertyInLiteral(reg, reg,
     359           1 :                                      DataPropertyInLiteralFlag::kNoFlags, 0);
     360             : 
     361             :   // Emit wide context operations.
     362           1 :   builder.LoadContextSlot(reg, 1024, 0, BytecodeArrayBuilder::kMutableSlot)
     363           1 :       .StoreContextSlot(reg, 1024, 0);
     364             : 
     365             :   // Emit wide load / store lookup slots.
     366           1 :   builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF)
     367           1 :       .LoadLookupSlot(wide_name, TypeofMode::INSIDE_TYPEOF)
     368             :       .StoreLookupSlot(wide_name, LanguageMode::kSloppy,
     369           1 :                        LookupHoistingMode::kNormal)
     370             :       .StoreLookupSlot(wide_name, LanguageMode::kSloppy,
     371           1 :                        LookupHoistingMode::kLegacySloppy)
     372             :       .StoreLookupSlot(wide_name, LanguageMode::kStrict,
     373           1 :                        LookupHoistingMode::kNormal);
     374             : 
     375             :   // CreateClosureWide
     376           1 :   builder.CreateClosure(1000, 321, NOT_TENURED);
     377             : 
     378             :   // Emit wide variant of literal creation operations.
     379             :   builder
     380           1 :       .CreateRegExpLiteral(ast_factory.GetOneByteString("wide_literal"), 0, 0)
     381           1 :       .CreateArrayLiteral(0, 0, 0)
     382           1 :       .CreateEmptyArrayLiteral(0)
     383           1 :       .CreateArrayFromIterable()
     384           1 :       .CreateObjectLiteral(0, 0, 0)
     385           1 :       .CreateEmptyObjectLiteral()
     386           1 :       .CloneObject(reg, 0, 0);
     387             : 
     388             :   // Emit load and store operations for module variables.
     389           1 :   builder.LoadModuleVariable(-1, 42)
     390           1 :       .LoadModuleVariable(0, 42)
     391           1 :       .LoadModuleVariable(1, 42)
     392           1 :       .StoreModuleVariable(-1, 42)
     393           1 :       .StoreModuleVariable(0, 42)
     394           1 :       .StoreModuleVariable(1, 42);
     395             : 
     396             :   // Emit generator operations.
     397             :   {
     398             :     // We have to skip over suspend because it returns and marks the remaining
     399             :     // bytecode dead.
     400             :     BytecodeLabel after_suspend;
     401           1 :     builder.JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &after_suspend)
     402           1 :         .SuspendGenerator(reg, reg_list, 0)
     403           1 :         .Bind(&after_suspend)
     404           1 :         .ResumeGenerator(reg, reg_list);
     405             :   }
     406           1 :   BytecodeJumpTable* gen_jump_table = builder.AllocateJumpTable(1, 0);
     407           1 :   builder.SwitchOnGeneratorState(reg, gen_jump_table).Bind(gen_jump_table, 0);
     408             : 
     409             :   // Intrinsics handled by the interpreter.
     410           1 :   builder.CallRuntime(Runtime::kInlineIsArray, reg_list);
     411             : 
     412             :   // Emit debugger bytecode.
     413           1 :   builder.Debugger();
     414             : 
     415             :   // Emit abort bytecode.
     416             :   {
     417             :     BytecodeLabel after;
     418           1 :     builder.Abort(AbortReason::kOperandIsASmi).Bind(&after);
     419             :   }
     420             : 
     421             :   // Insert dummy ops to force longer jumps.
     422         257 :   for (int i = 0; i < 256; i++) {
     423         256 :     builder.Debugger();
     424             :   }
     425             : 
     426             :   // Emit block counter increments.
     427           1 :   builder.IncBlockCounter(0);
     428             : 
     429             :   // Bind labels for long jumps at the very end.
     430          11 :   for (size_t i = 0; i < arraysize(end); i++) {
     431          10 :     builder.Bind(&end[i]);
     432             :   }
     433             : 
     434             :   // Return must be the last instruction.
     435           1 :   builder.Return();
     436             : 
     437             :   // Generate BytecodeArray.
     438           1 :   scope.SetScriptScopeInfo(factory->NewScopeInfo(1));
     439           1 :   ast_factory.Internalize(isolate());
     440           1 :   Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate());
     441           2 :   CHECK_EQ(the_array->frame_size(),
     442             :            builder.total_register_count() * kPointerSize);
     443             : 
     444             :   // Build scorecard of bytecodes encountered in the BytecodeArray.
     445           1 :   std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1);
     446             : 
     447             :   Bytecode final_bytecode = Bytecode::kLdaZero;
     448             :   int i = 0;
     449         466 :   while (i < the_array->length()) {
     450             :     uint8_t code = the_array->get(i);
     451         928 :     scorecard[code] += 1;
     452             :     final_bytecode = Bytecodes::FromByte(code);
     453             :     OperandScale operand_scale = OperandScale::kSingle;
     454             :     int prefix_offset = 0;
     455         464 :     if (Bytecodes::IsPrefixScalingBytecode(final_bytecode)) {
     456          15 :       operand_scale = Bytecodes::PrefixBytecodeToOperandScale(final_bytecode);
     457             :       prefix_offset = 1;
     458          15 :       code = the_array->get(i + 1);
     459          30 :       scorecard[code] += 1;
     460             :       final_bytecode = Bytecodes::FromByte(code);
     461             :     }
     462         464 :     i += prefix_offset + Bytecodes::Size(final_bytecode, operand_scale);
     463             :   }
     464             : 
     465             :   // Insert entry for illegal bytecode as this is never willingly emitted.
     466           1 :   scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1;
     467             : 
     468             :   // Bytecode for CollectTypeProfile is only emitted when
     469             :   // Type Information for DevTools is turned on.
     470           1 :   scorecard[Bytecodes::ToByte(Bytecode::kCollectTypeProfile)] = 1;
     471             : 
     472             :   // Check return occurs at the end and only once in the BytecodeArray.
     473           1 :   CHECK_EQ(final_bytecode, Bytecode::kReturn);
     474           2 :   CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
     475             : 
     476             : #define CHECK_BYTECODE_PRESENT(Name, ...)                                \
     477             :   /* Check Bytecode is marked in scorecard, unless it's a debug break */ \
     478             :   if (!Bytecodes::IsDebugBreak(Bytecode::k##Name)) {                     \
     479             :     EXPECT_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1);       \
     480             :   }
     481         180 :   BYTECODE_LIST(CHECK_BYTECODE_PRESENT)
     482             : #undef CHECK_BYTECODE_PRESENT
     483           1 : }
     484             : 
     485             : 
     486       15129 : TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
     487           6 :   for (int locals = 0; locals < 5; locals++) {
     488          15 :     for (int temps = 0; temps < 3; temps++) {
     489          15 :       BytecodeArrayBuilder builder(zone(), 1, locals);
     490             :       BytecodeRegisterAllocator* allocator(builder.register_allocator());
     491          45 :       for (int i = 0; i < locals; i++) {
     492          30 :         builder.LoadLiteral(Smi::zero());
     493          30 :         builder.StoreAccumulatorInRegister(Register(i));
     494             :       }
     495          15 :       for (int i = 0; i < temps; i++) {
     496          15 :         Register temp = allocator->NewRegister();
     497          15 :         builder.LoadLiteral(Smi::zero());
     498          15 :         builder.StoreAccumulatorInRegister(temp);
     499             :         // Ensure temporaries are used so not optimized away by the
     500             :         // register optimizer.
     501          15 :         builder.ToName(temp);
     502             :       }
     503          15 :       builder.Return();
     504             : 
     505          15 :       Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate());
     506          15 :       int total_registers = locals + temps;
     507          30 :       CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize);
     508          15 :     }
     509             :   }
     510           1 : }
     511             : 
     512             : 
     513       15129 : TEST_F(BytecodeArrayBuilderTest, RegisterValues) {
     514             :   int index = 1;
     515             : 
     516             :   Register the_register(index);
     517           1 :   CHECK_EQ(the_register.index(), index);
     518             : 
     519             :   int actual_operand = the_register.ToOperand();
     520             :   int actual_index = Register::FromOperand(actual_operand).index();
     521           1 :   CHECK_EQ(actual_index, index);
     522           1 : }
     523             : 
     524             : 
     525       15129 : TEST_F(BytecodeArrayBuilderTest, Parameters) {
     526           1 :   BytecodeArrayBuilder builder(zone(), 10, 0);
     527             : 
     528           1 :   Register receiver(builder.Receiver());
     529           1 :   Register param8(builder.Parameter(8));
     530           1 :   CHECK_EQ(param8.index() - receiver.index(), 9);
     531           1 : }
     532             : 
     533             : 
     534       15129 : TEST_F(BytecodeArrayBuilderTest, Constants) {
     535           1 :   BytecodeArrayBuilder builder(zone(), 1, 0);
     536             :   AstValueFactory ast_factory(zone(), isolate()->ast_string_constants(),
     537           2 :                               isolate()->heap()->HashSeed());
     538             : 
     539             :   double heap_num_1 = 3.14;
     540             :   double heap_num_2 = 5.2;
     541             :   double nan = std::numeric_limits<double>::quiet_NaN();
     542           1 :   const AstRawString* string = ast_factory.GetOneByteString("foo");
     543           1 :   const AstRawString* string_copy = ast_factory.GetOneByteString("foo");
     544             : 
     545           1 :   builder.LoadLiteral(heap_num_1)
     546           1 :       .LoadLiteral(heap_num_2)
     547           1 :       .LoadLiteral(string)
     548           1 :       .LoadLiteral(heap_num_1)
     549           1 :       .LoadLiteral(heap_num_1)
     550           1 :       .LoadLiteral(nan)
     551           1 :       .LoadLiteral(string_copy)
     552           1 :       .LoadLiteral(heap_num_2)
     553           1 :       .LoadLiteral(nan)
     554           1 :       .Return();
     555             : 
     556           1 :   ast_factory.Internalize(isolate());
     557           1 :   Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
     558             :   // Should only have one entry for each identical constant.
     559           4 :   EXPECT_EQ(4, array->constant_pool()->length());
     560           1 : }
     561             : 
     562       15129 : TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
     563             :   static const int kFarJumpDistance = 256 + 20;
     564             : 
     565           1 :   BytecodeArrayBuilder builder(zone(), 1, 1);
     566             : 
     567             :   Register reg(0);
     568             :   BytecodeLabel far0, far1, far2, far3, far4;
     569             :   BytecodeLabel near0, near1, near2, near3, near4;
     570             :   BytecodeLabel after_jump0, after_jump1;
     571             : 
     572           1 :   builder.Jump(&near0)
     573           1 :       .Bind(&after_jump0)
     574           1 :       .CompareOperation(Token::Value::EQ, reg, 1)
     575           1 :       .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &near1)
     576           1 :       .CompareOperation(Token::Value::EQ, reg, 2)
     577           1 :       .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &near2)
     578           1 :       .BinaryOperation(Token::Value::ADD, reg, 1)
     579           1 :       .JumpIfTrue(ToBooleanMode::kConvertToBoolean, &near3)
     580           1 :       .BinaryOperation(Token::Value::ADD, reg, 2)
     581           1 :       .JumpIfFalse(ToBooleanMode::kConvertToBoolean, &near4)
     582           1 :       .Bind(&near0)
     583           1 :       .Bind(&near1)
     584           1 :       .Bind(&near2)
     585           1 :       .Bind(&near3)
     586           1 :       .Bind(&near4)
     587           1 :       .Jump(&far0)
     588           1 :       .Bind(&after_jump1)
     589           1 :       .CompareOperation(Token::Value::EQ, reg, 3)
     590           1 :       .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &far1)
     591           1 :       .CompareOperation(Token::Value::EQ, reg, 4)
     592           1 :       .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &far2)
     593           1 :       .BinaryOperation(Token::Value::ADD, reg, 3)
     594           1 :       .JumpIfTrue(ToBooleanMode::kConvertToBoolean, &far3)
     595           1 :       .BinaryOperation(Token::Value::ADD, reg, 4)
     596           1 :       .JumpIfFalse(ToBooleanMode::kConvertToBoolean, &far4);
     597         255 :   for (int i = 0; i < kFarJumpDistance - 22; i++) {
     598         254 :     builder.Debugger();
     599             :   }
     600           1 :   builder.Bind(&far0).Bind(&far1).Bind(&far2).Bind(&far3).Bind(&far4);
     601           1 :   builder.Return();
     602             : 
     603           1 :   Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
     604             :   DCHECK_EQ(array->length(), 44 + kFarJumpDistance - 22 + 1);
     605             : 
     606           1 :   BytecodeArrayIterator iterator(array);
     607           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
     608           1 :   CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 22);
     609           1 :   iterator.Advance();
     610             : 
     611             :   // Ignore compare operation.
     612           1 :   iterator.Advance();
     613             : 
     614           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue);
     615           1 :   CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 17);
     616           1 :   iterator.Advance();
     617             : 
     618             :   // Ignore compare operation.
     619           1 :   iterator.Advance();
     620             : 
     621           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse);
     622           1 :   CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 12);
     623           1 :   iterator.Advance();
     624             : 
     625             :   // Ignore add operation.
     626           1 :   iterator.Advance();
     627             : 
     628           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue);
     629           1 :   CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 7);
     630           1 :   iterator.Advance();
     631             : 
     632             :   // Ignore add operation.
     633           1 :   iterator.Advance();
     634             : 
     635           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse);
     636           1 :   CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2);
     637           1 :   iterator.Advance();
     638             : 
     639           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant);
     640           2 :   CHECK_EQ(iterator.GetConstantForIndexOperand(0),
     641             :            Smi::FromInt(kFarJumpDistance));
     642           1 :   iterator.Advance();
     643             : 
     644             :   // Ignore compare operation.
     645           1 :   iterator.Advance();
     646             : 
     647           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant);
     648           2 :   CHECK_EQ(iterator.GetConstantForIndexOperand(0),
     649             :            Smi::FromInt(kFarJumpDistance - 5));
     650           1 :   iterator.Advance();
     651             : 
     652             :   // Ignore compare operation.
     653           1 :   iterator.Advance();
     654             : 
     655           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant);
     656           2 :   CHECK_EQ(iterator.GetConstantForIndexOperand(0),
     657             :            Smi::FromInt(kFarJumpDistance - 10));
     658           1 :   iterator.Advance();
     659             : 
     660             :   // Ignore add operation.
     661           1 :   iterator.Advance();
     662             : 
     663           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant);
     664           2 :   CHECK_EQ(iterator.GetConstantForIndexOperand(0),
     665             :            Smi::FromInt(kFarJumpDistance - 15));
     666           1 :   iterator.Advance();
     667             : 
     668             :   // Ignore add operation.
     669           1 :   iterator.Advance();
     670             : 
     671           1 :   CHECK_EQ(iterator.current_bytecode(),
     672             :            Bytecode::kJumpIfToBooleanFalseConstant);
     673           2 :   CHECK_EQ(iterator.GetConstantForIndexOperand(0),
     674             :            Smi::FromInt(kFarJumpDistance - 20));
     675           1 :   iterator.Advance();
     676           1 : }
     677             : 
     678             : 
     679       15129 : TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
     680           1 :   BytecodeArrayBuilder builder(zone(), 1, 1);
     681             : 
     682             :   Register reg(0);
     683             : 
     684             :   BytecodeLabel label0;
     685           1 :   builder.Bind(&label0).JumpLoop(&label0, 0);
     686          43 :   for (int i = 0; i < 42; i++) {
     687             :     BytecodeLabel after_jump;
     688          42 :     builder.JumpLoop(&label0, 0).Bind(&after_jump);
     689             :   }
     690             : 
     691             :   // Add padding to force wide backwards jumps.
     692         256 :   for (int i = 0; i < 256; i++) {
     693         256 :     builder.Debugger();
     694             :   }
     695             : 
     696           1 :   builder.JumpLoop(&label0, 0);
     697             :   BytecodeLabel end;
     698           1 :   builder.Bind(&end);
     699           1 :   builder.Return();
     700             : 
     701           1 :   Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
     702           1 :   BytecodeArrayIterator iterator(array);
     703           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
     704           1 :   CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0);
     705           1 :   iterator.Advance();
     706          44 :   for (unsigned i = 0; i < 42; i++) {
     707          42 :     CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
     708          42 :     CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
     709             :     // offset of 3 (because kJumpLoop takes two immediate operands)
     710          42 :     CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), i * 3 + 3);
     711          42 :     iterator.Advance();
     712             :   }
     713             :   // Check padding to force wide backwards jumps.
     714         256 :   for (int i = 0; i < 256; i++) {
     715         256 :     CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
     716         256 :     iterator.Advance();
     717             :   }
     718           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
     719           1 :   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
     720           1 :   CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 386);
     721           1 :   iterator.Advance();
     722           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
     723           1 :   iterator.Advance();
     724           1 :   CHECK(iterator.done());
     725           1 : }
     726             : 
     727       15129 : TEST_F(BytecodeArrayBuilderTest, SmallSwitch) {
     728           1 :   BytecodeArrayBuilder builder(zone(), 1, 1);
     729             : 
     730             :   // Small jump table that fits into the single-size constant pool
     731             :   int small_jump_table_size = 5;
     732             :   int small_jump_table_base = -2;
     733             :   BytecodeJumpTable* small_jump_table =
     734           1 :       builder.AllocateJumpTable(small_jump_table_size, small_jump_table_base);
     735             : 
     736           1 :   builder.LoadLiteral(Smi::FromInt(7)).SwitchOnSmiNoFeedback(small_jump_table);
     737           6 :   for (int i = 0; i < small_jump_table_size; i++) {
     738           5 :     builder.Bind(small_jump_table, small_jump_table_base + i).Debugger();
     739             :   }
     740           1 :   builder.Return();
     741             : 
     742           1 :   Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
     743           1 :   BytecodeArrayIterator iterator(array);
     744             : 
     745           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
     746           1 :   iterator.Advance();
     747             : 
     748           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kSwitchOnSmiNoFeedback);
     749           1 :   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
     750             :   {
     751             :     int i = 0;
     752             :     int switch_end =
     753           1 :         iterator.current_offset() + iterator.current_bytecode_size();
     754             : 
     755           6 :     for (const auto& entry : iterator.GetJumpTableTargetOffsets()) {
     756           5 :       CHECK_EQ(entry.case_value, small_jump_table_base + i);
     757           5 :       CHECK_EQ(entry.target_offset, switch_end + i);
     758             : 
     759           5 :       i++;
     760             :     }
     761           1 :     CHECK_EQ(i, small_jump_table_size);
     762             :   }
     763           1 :   iterator.Advance();
     764             : 
     765           6 :   for (int i = 0; i < small_jump_table_size; i++) {
     766           5 :     CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
     767           5 :     iterator.Advance();
     768             :   }
     769             : 
     770           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
     771           1 :   iterator.Advance();
     772           1 :   CHECK(iterator.done());
     773           1 : }
     774             : 
     775       15129 : TEST_F(BytecodeArrayBuilderTest, WideSwitch) {
     776           1 :   BytecodeArrayBuilder builder(zone(), 1, 1);
     777             : 
     778             :   // Large jump table that requires a wide Switch bytecode.
     779             :   int large_jump_table_size = 256;
     780             :   int large_jump_table_base = -10;
     781             :   BytecodeJumpTable* large_jump_table =
     782           1 :       builder.AllocateJumpTable(large_jump_table_size, large_jump_table_base);
     783             : 
     784           1 :   builder.LoadLiteral(Smi::FromInt(7)).SwitchOnSmiNoFeedback(large_jump_table);
     785         257 :   for (int i = 0; i < large_jump_table_size; i++) {
     786         256 :     builder.Bind(large_jump_table, large_jump_table_base + i).Debugger();
     787             :   }
     788           1 :   builder.Return();
     789             : 
     790           1 :   Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
     791           1 :   BytecodeArrayIterator iterator(array);
     792             : 
     793           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
     794           1 :   iterator.Advance();
     795             : 
     796           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kSwitchOnSmiNoFeedback);
     797           1 :   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
     798             :   {
     799             :     int i = 0;
     800             :     int switch_end =
     801           1 :         iterator.current_offset() + iterator.current_bytecode_size();
     802             : 
     803         257 :     for (const auto& entry : iterator.GetJumpTableTargetOffsets()) {
     804         256 :       CHECK_EQ(entry.case_value, large_jump_table_base + i);
     805         256 :       CHECK_EQ(entry.target_offset, switch_end + i);
     806             : 
     807         256 :       i++;
     808             :     }
     809           1 :     CHECK_EQ(i, large_jump_table_size);
     810             :   }
     811           1 :   iterator.Advance();
     812             : 
     813         257 :   for (int i = 0; i < large_jump_table_size; i++) {
     814         256 :     CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
     815         256 :     iterator.Advance();
     816             :   }
     817             : 
     818           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
     819           1 :   iterator.Advance();
     820           1 :   CHECK(iterator.done());
     821           1 : }
     822             : 
     823       15129 : TEST_F(BytecodeArrayBuilderTest, LabelReuse) {
     824           1 :   BytecodeArrayBuilder builder(zone(), 1, 0);
     825             : 
     826             :   // Labels can only have 1 forward reference, but
     827             :   // can be referred to mulitple times once bound.
     828             :   BytecodeLabel label, after_jump0, after_jump1;
     829             : 
     830           1 :   builder.Jump(&label)
     831           1 :       .Bind(&label)
     832           1 :       .JumpLoop(&label, 0)
     833           1 :       .Bind(&after_jump0)
     834           1 :       .JumpLoop(&label, 0)
     835           1 :       .Bind(&after_jump1)
     836           1 :       .Return();
     837             : 
     838           1 :   Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
     839           1 :   BytecodeArrayIterator iterator(array);
     840           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
     841           1 :   CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2);
     842           1 :   iterator.Advance();
     843           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
     844           1 :   CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0);
     845           1 :   iterator.Advance();
     846           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
     847           1 :   CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 3);
     848           1 :   iterator.Advance();
     849           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
     850           1 :   iterator.Advance();
     851           1 :   CHECK(iterator.done());
     852           1 : }
     853             : 
     854             : 
     855       15129 : TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) {
     856             :   static const int kRepeats = 3;
     857             : 
     858           1 :   BytecodeArrayBuilder builder(zone(), 1, 0);
     859           4 :   for (int i = 0; i < kRepeats; i++) {
     860             :     BytecodeLabel label, after_jump0, after_jump1;
     861           3 :     builder.Jump(&label)
     862           3 :         .Bind(&label)
     863           3 :         .JumpLoop(&label, 0)
     864           3 :         .Bind(&after_jump0)
     865           3 :         .JumpLoop(&label, 0)
     866           3 :         .Bind(&after_jump1);
     867             :   }
     868           1 :   builder.Return();
     869             : 
     870           1 :   Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
     871           1 :   BytecodeArrayIterator iterator(array);
     872           4 :   for (int i = 0; i < kRepeats; i++) {
     873           3 :     CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
     874           3 :     CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2);
     875           3 :     iterator.Advance();
     876           3 :     CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
     877           3 :     CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0);
     878           3 :     iterator.Advance();
     879           3 :     CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
     880           3 :     CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 3);
     881           3 :     iterator.Advance();
     882             :   }
     883           1 :   CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
     884           1 :   iterator.Advance();
     885           1 :   CHECK(iterator.done());
     886           1 : }
     887             : 
     888             : }  // namespace interpreter
     889             : }  // namespace internal
     890        9075 : }  // namespace v8

Generated by: LCOV version 1.10