blob: 7bbef45ad34c6d6f429a799f0267063b24ffc8cf [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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 "src/v8.h"
6
7#include "src/interpreter/bytecode-array-builder.h"
8#include "src/interpreter/bytecode-array-iterator.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +01009#include "src/interpreter/bytecode-label.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/interpreter/bytecode-register-allocator.h"
11#include "test/unittests/test-utils.h"
12
13namespace v8 {
14namespace internal {
15namespace interpreter {
16
17class BytecodeArrayBuilderTest : public TestWithIsolateAndZone {
18 public:
19 BytecodeArrayBuilderTest() {}
20 ~BytecodeArrayBuilderTest() override {}
21};
22
23
24TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010025 BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131);
Ben Murdochc5610432016-08-08 18:44:38 +010026 Factory* factory = isolate()->factory();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027
Ben Murdoch097c5b22016-05-18 11:27:45 +010028 CHECK_EQ(builder.locals_count(), 131);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029 CHECK_EQ(builder.context_count(), 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010030 CHECK_EQ(builder.fixed_register_count(), 132);
31
Ben Murdochc5610432016-08-08 18:44:38 +010032 Register reg(0);
33 Register other(reg.index() + 1);
34 Register wide(128);
35
Ben Murdoch097c5b22016-05-18 11:27:45 +010036 // Emit argument creation operations.
37 builder.CreateArguments(CreateArgumentsType::kMappedArguments)
38 .CreateArguments(CreateArgumentsType::kUnmappedArguments)
39 .CreateArguments(CreateArgumentsType::kRestParameter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040
41 // Emit constant loads.
42 builder.LoadLiteral(Smi::FromInt(0))
Ben Murdochc5610432016-08-08 18:44:38 +010043 .StoreAccumulatorInRegister(reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 .LoadLiteral(Smi::FromInt(8))
Ben Murdochc5610432016-08-08 18:44:38 +010045 .StoreAccumulatorInRegister(reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046 .LoadLiteral(Smi::FromInt(10000000))
Ben Murdochc5610432016-08-08 18:44:38 +010047 .StoreAccumulatorInRegister(reg)
48 .LoadLiteral(factory->NewStringFromStaticChars("A constant"))
49 .StoreAccumulatorInRegister(reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 .LoadUndefined()
Ben Murdoch61f157c2016-09-16 13:49:30 +010051 .Debugger() // Prevent peephole optimization LdaNull, Star -> LdrNull.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 .LoadNull()
Ben Murdochc5610432016-08-08 18:44:38 +010053 .StoreAccumulatorInRegister(reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054 .LoadTheHole()
Ben Murdochc5610432016-08-08 18:44:38 +010055 .StoreAccumulatorInRegister(reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 .LoadTrue()
Ben Murdochc5610432016-08-08 18:44:38 +010057 .StoreAccumulatorInRegister(reg)
58 .LoadFalse()
59 .StoreAccumulatorInRegister(wide);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060
Ben Murdoch61f157c2016-09-16 13:49:30 +010061 // Emit Ldar and Star taking care to foil the register optimizer.
Ben Murdochc5610432016-08-08 18:44:38 +010062 builder.StackCheck(0)
63 .LoadAccumulatorWithRegister(other)
Ben Murdoch61f157c2016-09-16 13:49:30 +010064 .BinaryOperation(Token::ADD, reg)
Ben Murdochc5610432016-08-08 18:44:38 +010065 .StoreAccumulatorInRegister(reg)
Ben Murdoch61f157c2016-09-16 13:49:30 +010066 .LoadNull();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067
68 // Emit register-register transfer.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069 builder.MoveRegister(reg, other);
Ben Murdoch097c5b22016-05-18 11:27:45 +010070 builder.MoveRegister(reg, wide);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071
72 // Emit global load / store operations.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 Handle<String> name = factory->NewStringFromStaticChars("var_name");
Ben Murdoch61f157c2016-09-16 13:49:30 +010074 builder.LoadGlobal(1, TypeofMode::NOT_INSIDE_TYPEOF)
75 .LoadGlobal(1, TypeofMode::INSIDE_TYPEOF)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 .StoreGlobal(name, 1, LanguageMode::SLOPPY)
77 .StoreGlobal(name, 1, LanguageMode::STRICT);
78
79 // Emit context operations.
80 builder.PushContext(reg)
81 .PopContext(reg)
82 .LoadContextSlot(reg, 1)
83 .StoreContextSlot(reg, 1);
84
85 // Emit load / store property operations.
Ben Murdoch097c5b22016-05-18 11:27:45 +010086 builder.LoadNamedProperty(reg, name, 0)
87 .LoadKeyedProperty(reg, 0)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 .StoreNamedProperty(reg, name, 0, LanguageMode::SLOPPY)
89 .StoreKeyedProperty(reg, reg, 0, LanguageMode::SLOPPY)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 .StoreNamedProperty(reg, name, 0, LanguageMode::STRICT)
91 .StoreKeyedProperty(reg, reg, 0, LanguageMode::STRICT);
92
93 // Emit load / store lookup slots.
94 builder.LoadLookupSlot(name, TypeofMode::NOT_INSIDE_TYPEOF)
95 .LoadLookupSlot(name, TypeofMode::INSIDE_TYPEOF)
96 .StoreLookupSlot(name, LanguageMode::SLOPPY)
97 .StoreLookupSlot(name, LanguageMode::STRICT);
98
99 // Emit closure operations.
100 Handle<SharedFunctionInfo> shared_info = factory->NewSharedFunctionInfo(
101 factory->NewStringFromStaticChars("function_a"), MaybeHandle<Code>(),
102 false);
103 builder.CreateClosure(shared_info, NOT_TENURED);
104
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105 // Emit literal creation operations.
106 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("a"), 0, 0)
107 .CreateArrayLiteral(factory->NewFixedArray(1), 0, 0)
108 .CreateObjectLiteral(factory->NewFixedArray(1), 0, 0);
109
110 // Call operations.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100111 builder.Call(reg, other, 1, 0)
112 .Call(reg, wide, 1, 0)
113 .TailCall(reg, other, 1, 0)
114 .TailCall(reg, wide, 1, 0)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 .CallRuntime(Runtime::kIsArray, reg, 1)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100116 .CallRuntime(Runtime::kIsArray, wide, 1)
117 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg, 1, other)
118 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, wide, 1, other)
119 .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg, 1)
120 .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, wide, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121
122 // Emit binary operator invocations.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100123 builder.BinaryOperation(Token::Value::ADD, reg)
124 .BinaryOperation(Token::Value::SUB, reg)
125 .BinaryOperation(Token::Value::MUL, reg)
126 .BinaryOperation(Token::Value::DIV, reg)
127 .BinaryOperation(Token::Value::MOD, reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128
129 // Emit bitwise operator invocations
Ben Murdoch097c5b22016-05-18 11:27:45 +0100130 builder.BinaryOperation(Token::Value::BIT_OR, reg)
131 .BinaryOperation(Token::Value::BIT_XOR, reg)
132 .BinaryOperation(Token::Value::BIT_AND, reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133
134 // Emit shift operator invocations
Ben Murdoch097c5b22016-05-18 11:27:45 +0100135 builder.BinaryOperation(Token::Value::SHL, reg)
136 .BinaryOperation(Token::Value::SAR, reg)
137 .BinaryOperation(Token::Value::SHR, reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138
139 // Emit count operatior invocations
Ben Murdoch097c5b22016-05-18 11:27:45 +0100140 builder.CountOperation(Token::Value::ADD).CountOperation(Token::Value::SUB);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141
142 // Emit unary operator invocations.
Ben Murdochc5610432016-08-08 18:44:38 +0100143 builder
144 .LogicalNot() // ToBooleanLogicalNot
145 .LogicalNot() // non-ToBoolean LogicalNot
146 .TypeOf();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147
148 // Emit delete
Ben Murdoch097c5b22016-05-18 11:27:45 +0100149 builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150
151 // Emit new.
152 builder.New(reg, reg, 0);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100153 builder.New(wide, wide, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154
155 // Emit test operator invocations.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100156 builder.CompareOperation(Token::Value::EQ, reg)
157 .CompareOperation(Token::Value::NE, reg)
158 .CompareOperation(Token::Value::EQ_STRICT, reg)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100159 .CompareOperation(Token::Value::LT, reg)
160 .CompareOperation(Token::Value::GT, reg)
161 .CompareOperation(Token::Value::LTE, reg)
162 .CompareOperation(Token::Value::GTE, reg)
163 .CompareOperation(Token::Value::INSTANCEOF, reg)
164 .CompareOperation(Token::Value::IN, reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165
166 // Emit cast operator invocations.
167 builder.CastAccumulatorToNumber()
168 .CastAccumulatorToJSObject()
169 .CastAccumulatorToName();
170
171 // Emit control flow. Return must be the last instruction.
172 BytecodeLabel start;
173 builder.Bind(&start);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100174 {
175 // Short jumps with Imm8 operands
176 BytecodeLabel after_jump;
177 builder.Jump(&start)
178 .Bind(&after_jump)
179 .JumpIfNull(&start)
180 .JumpIfUndefined(&start)
181 .JumpIfNotHole(&start);
182 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100183
Ben Murdochda12d292016-06-02 14:46:10 +0100184 // Longer jumps with constant operands
185 BytecodeLabel end[8];
Ben Murdoch61f157c2016-09-16 13:49:30 +0100186 {
187 BytecodeLabel after_jump;
188 builder.Jump(&end[0])
189 .Bind(&after_jump)
190 .LoadTrue()
191 .JumpIfTrue(&end[1])
192 .LoadTrue()
193 .JumpIfFalse(&end[2])
194 .LoadLiteral(Smi::FromInt(0))
195 .JumpIfTrue(&end[3])
196 .LoadLiteral(Smi::FromInt(0))
197 .JumpIfFalse(&end[4])
198 .JumpIfNull(&end[5])
199 .JumpIfUndefined(&end[6])
200 .JumpIfNotHole(&end[7]);
201 }
Ben Murdochda12d292016-06-02 14:46:10 +0100202
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 // Perform an operation that returns boolean value to
204 // generate JumpIfTrue/False
Ben Murdoch097c5b22016-05-18 11:27:45 +0100205 builder.CompareOperation(Token::Value::EQ, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 .JumpIfTrue(&start)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100207 .CompareOperation(Token::Value::EQ, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 .JumpIfFalse(&start);
209 // Perform an operation that returns a non-boolean operation to
210 // generate JumpIfToBooleanTrue/False.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100211 builder.BinaryOperation(Token::Value::ADD, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 .JumpIfTrue(&start)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100213 .BinaryOperation(Token::Value::ADD, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 .JumpIfFalse(&start);
215 // Insert dummy ops to force longer jumps
216 for (int i = 0; i < 128; i++) {
217 builder.LoadTrue();
218 }
219 // Longer jumps requiring Constant operand
Ben Murdoch61f157c2016-09-16 13:49:30 +0100220 {
221 BytecodeLabel after_jump;
222 builder.Jump(&start)
223 .Bind(&after_jump)
224 .JumpIfNull(&start)
225 .JumpIfUndefined(&start)
226 .JumpIfNotHole(&start);
227 // Perform an operation that returns boolean value to
228 // generate JumpIfTrue/False
229 builder.CompareOperation(Token::Value::EQ, reg)
230 .JumpIfTrue(&start)
231 .CompareOperation(Token::Value::EQ, reg)
232 .JumpIfFalse(&start);
233 // Perform an operation that returns a non-boolean operation to
234 // generate JumpIfToBooleanTrue/False.
235 builder.BinaryOperation(Token::Value::ADD, reg)
236 .JumpIfTrue(&start)
237 .BinaryOperation(Token::Value::ADD, reg)
238 .JumpIfFalse(&start);
239 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240
Ben Murdoch097c5b22016-05-18 11:27:45 +0100241 // Emit stack check bytecode.
Ben Murdochc5610432016-08-08 18:44:38 +0100242 builder.StackCheck(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243
Ben Murdoch097c5b22016-05-18 11:27:45 +0100244 // Emit throw and re-throw in it's own basic block so that the rest of the
245 // code isn't omitted due to being dead.
246 BytecodeLabel after_throw;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100247 builder.Throw().Bind(&after_throw);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100248 BytecodeLabel after_rethrow;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100249 builder.ReThrow().Bind(&after_rethrow);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100250
251 builder.ForInPrepare(reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 .ForInDone(reg, reg)
Ben Murdochda12d292016-06-02 14:46:10 +0100253 .ForInNext(reg, reg, reg, 1)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100254 .ForInStep(reg);
255 builder.ForInPrepare(wide)
256 .ForInDone(reg, other)
Ben Murdochda12d292016-06-02 14:46:10 +0100257 .ForInNext(wide, wide, wide, 1024)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258 .ForInStep(reg);
259
260 // Wide constant pool loads
261 for (int i = 0; i < 256; i++) {
262 // Emit junk in constant pool to force wide constant pool index.
263 builder.LoadLiteral(factory->NewNumber(2.5321 + i));
264 }
265 builder.LoadLiteral(Smi::FromInt(20000000));
266 Handle<String> wide_name = factory->NewStringFromStaticChars("var_wide_name");
267
268 // Emit wide global load / store operations.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100269 builder.LoadGlobal(1024, TypeofMode::NOT_INSIDE_TYPEOF)
270 .LoadGlobal(1024, TypeofMode::INSIDE_TYPEOF)
271 .LoadGlobal(1024, TypeofMode::INSIDE_TYPEOF)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 .StoreGlobal(name, 1024, LanguageMode::SLOPPY)
273 .StoreGlobal(wide_name, 1, LanguageMode::STRICT);
274
Ben Murdochda12d292016-06-02 14:46:10 +0100275 // Emit extra wide global load.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100276 builder.LoadGlobal(1024 * 1024, TypeofMode::NOT_INSIDE_TYPEOF);
Ben Murdochda12d292016-06-02 14:46:10 +0100277
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 // Emit wide load / store property operations.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100279 builder.LoadNamedProperty(reg, wide_name, 0)
280 .LoadKeyedProperty(reg, 2056)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 .StoreNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY)
282 .StoreKeyedProperty(reg, reg, 2056, LanguageMode::SLOPPY)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283 .StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT)
284 .StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT);
285
286 // Emit wide context operations.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100287 builder.LoadContextSlot(reg, 1024).StoreContextSlot(reg, 1024);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288
289 // Emit wide load / store lookup slots.
290 builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF)
291 .LoadLookupSlot(wide_name, TypeofMode::INSIDE_TYPEOF)
292 .StoreLookupSlot(wide_name, LanguageMode::SLOPPY)
293 .StoreLookupSlot(wide_name, LanguageMode::STRICT);
294
Ben Murdoch61f157c2016-09-16 13:49:30 +0100295 // Emit loads which will be transformed to Ldr equivalents by the peephole
296 // optimizer.
297 builder.LoadNamedProperty(reg, name, 0)
298 .StoreAccumulatorInRegister(reg)
299 .LoadKeyedProperty(reg, 0)
300 .StoreAccumulatorInRegister(reg)
301 .LoadContextSlot(reg, 1)
302 .StoreAccumulatorInRegister(reg)
303 .LoadGlobal(0, TypeofMode::NOT_INSIDE_TYPEOF)
304 .StoreAccumulatorInRegister(reg)
305 .LoadUndefined()
306 .StoreAccumulatorInRegister(reg);
307
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000308 // CreateClosureWide
309 Handle<SharedFunctionInfo> shared_info2 = factory->NewSharedFunctionInfo(
310 factory->NewStringFromStaticChars("function_b"), MaybeHandle<Code>(),
311 false);
312 builder.CreateClosure(shared_info2, NOT_TENURED);
313
314 // Emit wide variant of literal creation operations.
315 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("wide_literal"),
316 0, 0)
317 .CreateArrayLiteral(factory->NewFixedArray(2), 0, 0)
318 .CreateObjectLiteral(factory->NewFixedArray(2), 0, 0);
319
320 // Longer jumps requiring ConstantWide operand
Ben Murdoch61f157c2016-09-16 13:49:30 +0100321 {
322 BytecodeLabel after_jump;
323 builder.Jump(&start)
324 .Bind(&after_jump)
325 .JumpIfNull(&start)
326 .JumpIfUndefined(&start)
327 .JumpIfNotHole(&start);
328 }
329
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330 // Perform an operation that returns boolean value to
331 // generate JumpIfTrue/False
Ben Murdoch097c5b22016-05-18 11:27:45 +0100332 builder.CompareOperation(Token::Value::EQ, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333 .JumpIfTrue(&start)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100334 .CompareOperation(Token::Value::EQ, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335 .JumpIfFalse(&start);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100336
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337 // Perform an operation that returns a non-boolean operation to
338 // generate JumpIfToBooleanTrue/False.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100339 builder.BinaryOperation(Token::Value::ADD, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 .JumpIfTrue(&start)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100341 .BinaryOperation(Token::Value::ADD, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000342 .JumpIfFalse(&start);
343
Ben Murdochc5610432016-08-08 18:44:38 +0100344 // Emit generator operations
345 builder.SuspendGenerator(reg)
346 .ResumeGenerator(reg);
347
Ben Murdochda12d292016-06-02 14:46:10 +0100348 // Intrinsics handled by the interpreter.
349 builder.CallRuntime(Runtime::kInlineIsArray, reg, 1)
350 .CallRuntime(Runtime::kInlineIsArray, wide, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100351
Ben Murdochda12d292016-06-02 14:46:10 +0100352 builder.Debugger();
353 for (size_t i = 0; i < arraysize(end); i++) {
354 builder.Bind(&end[i]);
355 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356 builder.Return();
357
358 // Generate BytecodeArray.
359 Handle<BytecodeArray> the_array = builder.ToBytecodeArray();
360 CHECK_EQ(the_array->frame_size(),
Ben Murdochda12d292016-06-02 14:46:10 +0100361 builder.fixed_and_temporary_register_count() * kPointerSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362
363 // Build scorecard of bytecodes encountered in the BytecodeArray.
364 std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1);
Ben Murdochda12d292016-06-02 14:46:10 +0100365
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 Bytecode final_bytecode = Bytecode::kLdaZero;
367 int i = 0;
368 while (i < the_array->length()) {
369 uint8_t code = the_array->get(i);
370 scorecard[code] += 1;
371 final_bytecode = Bytecodes::FromByte(code);
Ben Murdochda12d292016-06-02 14:46:10 +0100372 OperandScale operand_scale = OperandScale::kSingle;
373 int prefix_offset = 0;
374 if (Bytecodes::IsPrefixScalingBytecode(final_bytecode)) {
375 operand_scale = Bytecodes::PrefixBytecodeToOperandScale(final_bytecode);
376 prefix_offset = 1;
377 code = the_array->get(i + 1);
378 final_bytecode = Bytecodes::FromByte(code);
379 }
380 i += prefix_offset + Bytecodes::Size(final_bytecode, operand_scale);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 }
382
Ben Murdochda12d292016-06-02 14:46:10 +0100383 // Insert entry for illegal bytecode as this is never willingly emitted.
384 scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1;
385
Ben Murdochc5610432016-08-08 18:44:38 +0100386 // Insert entry for nop bytecode as this often gets optimized out.
387 scorecard[Bytecodes::ToByte(Bytecode::kNop)] = 1;
388
Ben Murdoch61f157c2016-09-16 13:49:30 +0100389 if (!FLAG_ignition_peephole) {
390 // Insert entries for bytecodes only emitted by peephole optimizer.
391 scorecard[Bytecodes::ToByte(Bytecode::kLdrNamedProperty)] = 1;
392 scorecard[Bytecodes::ToByte(Bytecode::kLdrKeyedProperty)] = 1;
393 scorecard[Bytecodes::ToByte(Bytecode::kLdrGlobal)] = 1;
394 scorecard[Bytecodes::ToByte(Bytecode::kLdrContextSlot)] = 1;
395 scorecard[Bytecodes::ToByte(Bytecode::kLdrUndefined)] = 1;
396 scorecard[Bytecodes::ToByte(Bytecode::kLogicalNot)] = 1;
397 scorecard[Bytecodes::ToByte(Bytecode::kJump)] = 1;
398 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfTrue)] = 1;
399 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfFalse)] = 1;
400 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfTrueConstant)] = 1;
401 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfFalseConstant)] = 1;
402 }
403
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000404 // Check return occurs at the end and only once in the BytecodeArray.
405 CHECK_EQ(final_bytecode, Bytecode::kReturn);
406 CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
407
Ben Murdoch097c5b22016-05-18 11:27:45 +0100408#define CHECK_BYTECODE_PRESENT(Name, ...) \
409 /* Check Bytecode is marked in scorecard, unless it's a debug break */ \
410 if (!Bytecodes::IsDebugBreak(Bytecode::k##Name)) { \
411 CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); \
412 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000413 BYTECODE_LIST(CHECK_BYTECODE_PRESENT)
414#undef CHECK_BYTECODE_PRESENT
415}
416
417
418TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
419 for (int locals = 0; locals < 5; locals++) {
420 for (int contexts = 0; contexts < 4; contexts++) {
421 for (int temps = 0; temps < 3; temps++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100422 BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals);
423 BytecodeRegisterAllocator temporaries(
424 zone(), builder.temporary_register_allocator());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100425 for (int i = 0; i < locals + contexts; i++) {
426 builder.LoadLiteral(Smi::FromInt(0));
427 builder.StoreAccumulatorInRegister(Register(i));
428 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000429 for (int i = 0; i < temps; i++) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100430 builder.LoadLiteral(Smi::FromInt(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000431 builder.StoreAccumulatorInRegister(temporaries.NewRegister());
432 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100433 if (temps > 0) {
434 // Ensure temporaries are used so not optimized away by the
435 // register optimizer.
436 builder.New(Register(locals + contexts), Register(locals + contexts),
437 static_cast<size_t>(temps));
438 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 builder.Return();
440
441 Handle<BytecodeArray> the_array = builder.ToBytecodeArray();
442 int total_registers = locals + contexts + temps;
443 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize);
444 }
445 }
446 }
447}
448
449
450TEST_F(BytecodeArrayBuilderTest, RegisterValues) {
451 int index = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452
453 Register the_register(index);
454 CHECK_EQ(the_register.index(), index);
455
456 int actual_operand = the_register.ToOperand();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 int actual_index = Register::FromOperand(actual_operand).index();
458 CHECK_EQ(actual_index, index);
459}
460
461
462TEST_F(BytecodeArrayBuilderTest, Parameters) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100463 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100464
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000465 Register param0(builder.Parameter(0));
466 Register param9(builder.Parameter(9));
467 CHECK_EQ(param9.index() - param0.index(), 9);
468}
469
470
471TEST_F(BytecodeArrayBuilderTest, RegisterType) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100472 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3);
473 BytecodeRegisterAllocator register_allocator(
474 zone(), builder.temporary_register_allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475 Register temp0 = register_allocator.NewRegister();
476 Register param0(builder.Parameter(0));
477 Register param9(builder.Parameter(9));
478 Register temp1 = register_allocator.NewRegister();
479 Register reg0(0);
480 Register reg1(1);
481 Register reg2(2);
482 Register temp2 = register_allocator.NewRegister();
483 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp0), false);
484 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp1), false);
485 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp2), false);
486 CHECK_EQ(builder.RegisterIsParameterOrLocal(param0), true);
487 CHECK_EQ(builder.RegisterIsParameterOrLocal(param9), true);
488 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg0), true);
489 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg1), true);
490 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg2), true);
491}
492
493
494TEST_F(BytecodeArrayBuilderTest, Constants) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100495 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100496
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 Factory* factory = isolate()->factory();
498 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14);
499 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2);
500 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate());
501 Handle<HeapObject> heap_num_2_copy(*heap_num_2);
502 builder.LoadLiteral(heap_num_1)
503 .LoadLiteral(heap_num_2)
504 .LoadLiteral(large_smi)
505 .LoadLiteral(heap_num_1)
506 .LoadLiteral(heap_num_1)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100507 .LoadLiteral(heap_num_2_copy)
508 .Return();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509
510 Handle<BytecodeArray> array = builder.ToBytecodeArray();
511 // Should only have one entry for each identical constant.
512 CHECK_EQ(array->constant_pool()->length(), 3);
513}
514
Ben Murdoch61f157c2016-09-16 13:49:30 +0100515static Bytecode PeepholeToBoolean(Bytecode jump_bytecode) {
516 return FLAG_ignition_peephole
517 ? Bytecodes::GetJumpWithoutToBoolean(jump_bytecode)
518 : jump_bytecode;
519}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000520
521TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
522 static const int kFarJumpDistance = 256;
523
Ben Murdoch097c5b22016-05-18 11:27:45 +0100524 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100525
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526 Register reg(0);
527 BytecodeLabel far0, far1, far2, far3, far4;
528 BytecodeLabel near0, near1, near2, near3, near4;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100529 BytecodeLabel after_jump0, after_jump1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000530
531 builder.Jump(&near0)
Ben Murdoch61f157c2016-09-16 13:49:30 +0100532 .Bind(&after_jump0)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100533 .CompareOperation(Token::Value::EQ, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000534 .JumpIfTrue(&near1)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100535 .CompareOperation(Token::Value::EQ, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536 .JumpIfFalse(&near2)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100537 .BinaryOperation(Token::Value::ADD, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000538 .JumpIfTrue(&near3)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100539 .BinaryOperation(Token::Value::ADD, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000540 .JumpIfFalse(&near4)
541 .Bind(&near0)
542 .Bind(&near1)
543 .Bind(&near2)
544 .Bind(&near3)
545 .Bind(&near4)
546 .Jump(&far0)
Ben Murdoch61f157c2016-09-16 13:49:30 +0100547 .Bind(&after_jump1)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100548 .CompareOperation(Token::Value::EQ, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 .JumpIfTrue(&far1)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100550 .CompareOperation(Token::Value::EQ, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000551 .JumpIfFalse(&far2)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100552 .BinaryOperation(Token::Value::ADD, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000553 .JumpIfTrue(&far3)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100554 .BinaryOperation(Token::Value::ADD, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 .JumpIfFalse(&far4);
556 for (int i = 0; i < kFarJumpDistance - 18; i++) {
Ben Murdochc5610432016-08-08 18:44:38 +0100557 builder.Debugger();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 }
559 builder.Bind(&far0).Bind(&far1).Bind(&far2).Bind(&far3).Bind(&far4);
560 builder.Return();
561
562 Handle<BytecodeArray> array = builder.ToBytecodeArray();
563 DCHECK_EQ(array->length(), 36 + kFarJumpDistance - 18 + 1);
564
565 BytecodeArrayIterator iterator(array);
566 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
567 CHECK_EQ(iterator.GetImmediateOperand(0), 18);
568 iterator.Advance();
569
570 // Ignore compare operation.
571 iterator.Advance();
572
Ben Murdoch61f157c2016-09-16 13:49:30 +0100573 CHECK_EQ(iterator.current_bytecode(),
574 PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000575 CHECK_EQ(iterator.GetImmediateOperand(0), 14);
576 iterator.Advance();
577
578 // Ignore compare operation.
579 iterator.Advance();
580
Ben Murdoch61f157c2016-09-16 13:49:30 +0100581 CHECK_EQ(iterator.current_bytecode(),
582 PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583 CHECK_EQ(iterator.GetImmediateOperand(0), 10);
584 iterator.Advance();
585
586 // Ignore add operation.
587 iterator.Advance();
588
589 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue);
590 CHECK_EQ(iterator.GetImmediateOperand(0), 6);
591 iterator.Advance();
592
593 // Ignore add operation.
594 iterator.Advance();
595
596 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse);
597 CHECK_EQ(iterator.GetImmediateOperand(0), 2);
598 iterator.Advance();
599
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant);
601 CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
602 Smi::FromInt(kFarJumpDistance));
603 iterator.Advance();
604
605 // Ignore compare operation.
606 iterator.Advance();
607
Ben Murdoch61f157c2016-09-16 13:49:30 +0100608 CHECK_EQ(iterator.current_bytecode(),
609 PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrueConstant));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
611 Smi::FromInt(kFarJumpDistance - 4));
612 iterator.Advance();
613
614 // Ignore compare operation.
615 iterator.Advance();
616
Ben Murdoch61f157c2016-09-16 13:49:30 +0100617 CHECK_EQ(iterator.current_bytecode(),
618 PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalseConstant));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000619 CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
620 Smi::FromInt(kFarJumpDistance - 8));
621 iterator.Advance();
622
623 // Ignore add operation.
624 iterator.Advance();
625
626 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant);
627 CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
628 Smi::FromInt(kFarJumpDistance - 12));
629 iterator.Advance();
630
631 // Ignore add operation.
632 iterator.Advance();
633
634 CHECK_EQ(iterator.current_bytecode(),
635 Bytecode::kJumpIfToBooleanFalseConstant);
636 CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
637 Smi::FromInt(kFarJumpDistance - 16));
638 iterator.Advance();
639}
640
641
642TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100643 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100644
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000645 Register reg(0);
646
647 BytecodeLabel label0, label1, label2, label3, label4;
648 builder.Bind(&label0)
649 .Jump(&label0)
650 .Bind(&label1)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100651 .CompareOperation(Token::Value::EQ, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652 .JumpIfTrue(&label1)
653 .Bind(&label2)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100654 .CompareOperation(Token::Value::EQ, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655 .JumpIfFalse(&label2)
656 .Bind(&label3)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100657 .BinaryOperation(Token::Value::ADD, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000658 .JumpIfTrue(&label3)
659 .Bind(&label4)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100660 .BinaryOperation(Token::Value::ADD, reg)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000661 .JumpIfFalse(&label4);
662 for (int i = 0; i < 63; i++) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100663 BytecodeLabel after_jump;
664 builder.Jump(&label4).Bind(&after_jump);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000665 }
Ben Murdochda12d292016-06-02 14:46:10 +0100666
667 // Add padding to force wide backwards jumps.
668 for (int i = 0; i < 256; i++) {
Ben Murdochc5610432016-08-08 18:44:38 +0100669 builder.Debugger();
Ben Murdochda12d292016-06-02 14:46:10 +0100670 }
671
Ben Murdoch097c5b22016-05-18 11:27:45 +0100672 builder.BinaryOperation(Token::Value::ADD, reg).JumpIfFalse(&label4);
673 builder.BinaryOperation(Token::Value::ADD, reg).JumpIfTrue(&label3);
674 builder.CompareOperation(Token::Value::EQ, reg).JumpIfFalse(&label2);
675 builder.CompareOperation(Token::Value::EQ, reg).JumpIfTrue(&label1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000676 builder.Jump(&label0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100677 BytecodeLabel end;
678 builder.Bind(&end);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679 builder.Return();
680
681 Handle<BytecodeArray> array = builder.ToBytecodeArray();
682 BytecodeArrayIterator iterator(array);
683 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
684 CHECK_EQ(iterator.GetImmediateOperand(0), 0);
685 iterator.Advance();
686 // Ignore compare operation.
687 iterator.Advance();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100688 CHECK_EQ(iterator.current_bytecode(),
689 PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue));
Ben Murdochda12d292016-06-02 14:46:10 +0100690 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691 CHECK_EQ(iterator.GetImmediateOperand(0), -2);
692 iterator.Advance();
693 // Ignore compare operation.
694 iterator.Advance();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100695 CHECK_EQ(iterator.current_bytecode(),
696 PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse));
Ben Murdochda12d292016-06-02 14:46:10 +0100697 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000698 CHECK_EQ(iterator.GetImmediateOperand(0), -2);
699 iterator.Advance();
700 // Ignore binary operation.
701 iterator.Advance();
702 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue);
Ben Murdochda12d292016-06-02 14:46:10 +0100703 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000704 CHECK_EQ(iterator.GetImmediateOperand(0), -2);
705 iterator.Advance();
706 // Ignore binary operation.
707 iterator.Advance();
708 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse);
Ben Murdochda12d292016-06-02 14:46:10 +0100709 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000710 CHECK_EQ(iterator.GetImmediateOperand(0), -2);
711 iterator.Advance();
712 for (int i = 0; i < 63; i++) {
713 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
Ben Murdochda12d292016-06-02 14:46:10 +0100714 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000715 CHECK_EQ(iterator.GetImmediateOperand(0), -i * 2 - 4);
716 iterator.Advance();
717 }
Ben Murdochda12d292016-06-02 14:46:10 +0100718 // Check padding to force wide backwards jumps.
719 for (int i = 0; i < 256; i++) {
Ben Murdochc5610432016-08-08 18:44:38 +0100720 CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
Ben Murdochda12d292016-06-02 14:46:10 +0100721 iterator.Advance();
722 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723 // Ignore binary operation.
724 iterator.Advance();
Ben Murdochda12d292016-06-02 14:46:10 +0100725 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse);
726 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
727 CHECK_EQ(iterator.GetImmediateOperand(0), -389);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000728 iterator.Advance();
729 // Ignore binary operation.
730 iterator.Advance();
Ben Murdochda12d292016-06-02 14:46:10 +0100731 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue);
732 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
733 CHECK_EQ(iterator.GetImmediateOperand(0), -399);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000734 iterator.Advance();
735 // Ignore compare operation.
736 iterator.Advance();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100737 CHECK_EQ(iterator.current_bytecode(),
738 PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse));
Ben Murdochda12d292016-06-02 14:46:10 +0100739 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
740 CHECK_EQ(iterator.GetImmediateOperand(0), -409);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 iterator.Advance();
742 // Ignore compare operation.
743 iterator.Advance();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100744 CHECK_EQ(iterator.current_bytecode(),
745 PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue));
Ben Murdochda12d292016-06-02 14:46:10 +0100746 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
747 CHECK_EQ(iterator.GetImmediateOperand(0), -419);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000748 iterator.Advance();
Ben Murdochda12d292016-06-02 14:46:10 +0100749 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
750 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
751 CHECK_EQ(iterator.GetImmediateOperand(0), -425);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000752 iterator.Advance();
753 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
754 iterator.Advance();
755 CHECK(iterator.done());
756}
757
758
759TEST_F(BytecodeArrayBuilderTest, LabelReuse) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100760 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000761
762 // Labels can only have 1 forward reference, but
763 // can be referred to mulitple times once bound.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100764 BytecodeLabel label, after_jump0, after_jump1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765
Ben Murdoch61f157c2016-09-16 13:49:30 +0100766 builder.Jump(&label)
767 .Bind(&label)
768 .Jump(&label)
769 .Bind(&after_jump0)
770 .Jump(&label)
771 .Bind(&after_jump1)
772 .Return();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000773
774 Handle<BytecodeArray> array = builder.ToBytecodeArray();
775 BytecodeArrayIterator iterator(array);
776 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
777 CHECK_EQ(iterator.GetImmediateOperand(0), 2);
778 iterator.Advance();
779 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
780 CHECK_EQ(iterator.GetImmediateOperand(0), 0);
781 iterator.Advance();
782 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
783 CHECK_EQ(iterator.GetImmediateOperand(0), -2);
784 iterator.Advance();
785 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
786 iterator.Advance();
787 CHECK(iterator.done());
788}
789
790
791TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) {
792 static const int kRepeats = 3;
793
Ben Murdoch097c5b22016-05-18 11:27:45 +0100794 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000795 for (int i = 0; i < kRepeats; i++) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100796 BytecodeLabel label, after_jump0, after_jump1;
797 builder.Jump(&label)
798 .Bind(&label)
799 .Jump(&label)
800 .Bind(&after_jump0)
801 .Jump(&label)
802 .Bind(&after_jump1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000803 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000804 builder.Return();
805
806 Handle<BytecodeArray> array = builder.ToBytecodeArray();
807 BytecodeArrayIterator iterator(array);
808 for (int i = 0; i < kRepeats; i++) {
809 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
810 CHECK_EQ(iterator.GetImmediateOperand(0), 2);
811 iterator.Advance();
812 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
813 CHECK_EQ(iterator.GetImmediateOperand(0), 0);
814 iterator.Advance();
815 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
816 CHECK_EQ(iterator.GetImmediateOperand(0), -2);
817 iterator.Advance();
818 }
819 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
820 iterator.Advance();
821 CHECK(iterator.done());
822}
823
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824} // namespace interpreter
825} // namespace internal
826} // namespace v8