OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/interpreter/bytecode-array-builder.h" | 7 #include "src/interpreter/bytecode-array-builder.h" |
8 #include "src/interpreter/bytecode-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
9 #include "test/unittests/test-utils.h" | 9 #include "test/unittests/test-utils.h" |
10 | 10 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 builder.Jump(&start).JumpIfTrue(&start).JumpIfFalse(&start); | 87 builder.Jump(&start).JumpIfTrue(&start).JumpIfFalse(&start); |
88 builder.Return(); | 88 builder.Return(); |
89 | 89 |
90 // Generate BytecodeArray. | 90 // Generate BytecodeArray. |
91 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); | 91 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); |
92 CHECK_EQ(the_array->frame_size(), builder.locals_count() * kPointerSize); | 92 CHECK_EQ(the_array->frame_size(), builder.locals_count() * kPointerSize); |
93 | 93 |
94 // Build scorecard of bytecodes encountered in the BytecodeArray. | 94 // Build scorecard of bytecodes encountered in the BytecodeArray. |
95 std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1); | 95 std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1); |
96 Bytecode final_bytecode = Bytecode::kLdaZero; | 96 Bytecode final_bytecode = Bytecode::kLdaZero; |
97 for (int i = 0; i < the_array->length(); i++) { | 97 int i = 0; |
| 98 while (i < the_array->length()) { |
98 uint8_t code = the_array->get(i); | 99 uint8_t code = the_array->get(i); |
99 scorecard[code] += 1; | 100 scorecard[code] += 1; |
100 int operands = Bytecodes::NumberOfOperands(Bytecodes::FromByte(code)); | |
101 CHECK_LE(operands, Bytecodes::MaximumNumberOfOperands()); | |
102 final_bytecode = Bytecodes::FromByte(code); | 101 final_bytecode = Bytecodes::FromByte(code); |
103 i += operands; | 102 i += Bytecodes::Size(Bytecodes::FromByte(code)); |
104 } | 103 } |
105 | 104 |
106 // Check return occurs at the end and only once in the BytecodeArray. | 105 // Check return occurs at the end and only once in the BytecodeArray. |
107 CHECK_EQ(final_bytecode, Bytecode::kReturn); | 106 CHECK_EQ(final_bytecode, Bytecode::kReturn); |
108 CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1); | 107 CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1); |
109 | 108 |
110 #define CHECK_BYTECODE_PRESENT(Name, ...) \ | 109 #define CHECK_BYTECODE_PRESENT(Name, ...) \ |
111 /* Check Bytecode is marked in scorecard */ \ | 110 /* Check Bytecode is marked in scorecard */ \ |
112 CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); | 111 CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); |
113 BYTECODE_LIST(CHECK_BYTECODE_PRESENT) | 112 BYTECODE_LIST(CHECK_BYTECODE_PRESENT) |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 builder.LoadUndefined(); | 232 builder.LoadUndefined(); |
234 } | 233 } |
235 builder.Bind(&far0).Bind(&far1).Bind(&far2); | 234 builder.Bind(&far0).Bind(&far1).Bind(&far2); |
236 builder.Return(); | 235 builder.Return(); |
237 | 236 |
238 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 237 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
239 DCHECK_EQ(array->length(), 12 + kFarJumpDistance - 6 + 1); | 238 DCHECK_EQ(array->length(), 12 + kFarJumpDistance - 6 + 1); |
240 | 239 |
241 BytecodeArrayIterator iterator(array); | 240 BytecodeArrayIterator iterator(array); |
242 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 241 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
243 CHECK_EQ(iterator.GetSmi8Operand(0), 6); | 242 CHECK_EQ(iterator.GetImmediateOperand(0), 6); |
244 iterator.Advance(); | 243 iterator.Advance(); |
245 | 244 |
246 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); | 245 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); |
247 CHECK_EQ(iterator.GetSmi8Operand(0), 4); | 246 CHECK_EQ(iterator.GetImmediateOperand(0), 4); |
248 iterator.Advance(); | 247 iterator.Advance(); |
249 | 248 |
250 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); | 249 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); |
251 CHECK_EQ(iterator.GetSmi8Operand(0), 2); | 250 CHECK_EQ(iterator.GetImmediateOperand(0), 2); |
252 iterator.Advance(); | 251 iterator.Advance(); |
253 | 252 |
254 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); | 253 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); |
255 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 254 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
256 Smi::FromInt(kFarJumpDistance)); | 255 Smi::FromInt(kFarJumpDistance)); |
257 CHECK_EQ( | 256 CHECK_EQ( |
258 array->get(iterator.current_offset() + | 257 array->get(iterator.current_offset() + |
259 Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()), | 258 Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()), |
260 Bytecodes::ToByte(Bytecode::kReturn)); | 259 Bytecodes::ToByte(Bytecode::kReturn)); |
261 iterator.Advance(); | 260 iterator.Advance(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 builder.Jump(&label2); | 295 builder.Jump(&label2); |
297 } | 296 } |
298 builder.JumpIfFalse(&label2); | 297 builder.JumpIfFalse(&label2); |
299 builder.JumpIfTrue(&label1); | 298 builder.JumpIfTrue(&label1); |
300 builder.Jump(&label0); | 299 builder.Jump(&label0); |
301 builder.Return(); | 300 builder.Return(); |
302 | 301 |
303 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 302 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
304 BytecodeArrayIterator iterator(array); | 303 BytecodeArrayIterator iterator(array); |
305 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 304 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
306 CHECK_EQ(iterator.GetSmi8Operand(0), 0); | 305 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
307 iterator.Advance(); | 306 iterator.Advance(); |
308 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); | 307 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); |
309 CHECK_EQ(iterator.GetSmi8Operand(0), 0); | 308 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
310 iterator.Advance(); | 309 iterator.Advance(); |
311 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); | 310 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); |
312 CHECK_EQ(iterator.GetSmi8Operand(0), 0); | 311 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
313 iterator.Advance(); | 312 iterator.Advance(); |
314 for (int i = 0; i < 64; i++) { | 313 for (int i = 0; i < 64; i++) { |
315 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 314 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
316 CHECK_EQ(iterator.GetSmi8Operand(0), -i * 2 - 2); | 315 CHECK_EQ(iterator.GetImmediateOperand(0), -i * 2 - 2); |
317 iterator.Advance(); | 316 iterator.Advance(); |
318 } | 317 } |
319 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); | 318 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); |
320 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -130); | 319 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -130); |
321 iterator.Advance(); | 320 iterator.Advance(); |
322 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); | 321 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); |
323 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -134); | 322 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -134); |
324 iterator.Advance(); | 323 iterator.Advance(); |
325 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); | 324 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); |
326 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -138); | 325 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -138); |
(...skipping 11 matching lines...) Expand all Loading... |
338 | 337 |
339 // Labels can only have 1 forward reference, but | 338 // Labels can only have 1 forward reference, but |
340 // can be referred to mulitple times once bound. | 339 // can be referred to mulitple times once bound. |
341 BytecodeLabel label; | 340 BytecodeLabel label; |
342 | 341 |
343 builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label).Return(); | 342 builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label).Return(); |
344 | 343 |
345 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 344 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
346 BytecodeArrayIterator iterator(array); | 345 BytecodeArrayIterator iterator(array); |
347 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 346 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
348 CHECK_EQ(iterator.GetSmi8Operand(0), 2); | 347 CHECK_EQ(iterator.GetImmediateOperand(0), 2); |
349 iterator.Advance(); | 348 iterator.Advance(); |
350 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 349 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
351 CHECK_EQ(iterator.GetSmi8Operand(0), 0); | 350 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
352 iterator.Advance(); | 351 iterator.Advance(); |
353 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 352 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
354 CHECK_EQ(iterator.GetSmi8Operand(0), -2); | 353 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
355 iterator.Advance(); | 354 iterator.Advance(); |
356 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 355 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
357 iterator.Advance(); | 356 iterator.Advance(); |
358 CHECK(iterator.done()); | 357 CHECK(iterator.done()); |
359 } | 358 } |
360 | 359 |
361 | 360 |
362 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { | 361 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { |
363 static const int kRepeats = 3; | 362 static const int kRepeats = 3; |
364 | 363 |
365 BytecodeArrayBuilder builder(isolate(), zone()); | 364 BytecodeArrayBuilder builder(isolate(), zone()); |
366 builder.set_parameter_count(0); | 365 builder.set_parameter_count(0); |
367 builder.set_locals_count(0); | 366 builder.set_locals_count(0); |
368 | 367 |
369 for (int i = 0; i < kRepeats; i++) { | 368 for (int i = 0; i < kRepeats; i++) { |
370 BytecodeLabel label; | 369 BytecodeLabel label; |
371 builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label); | 370 builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label); |
372 } | 371 } |
373 | 372 |
374 builder.Return(); | 373 builder.Return(); |
375 | 374 |
376 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 375 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
377 BytecodeArrayIterator iterator(array); | 376 BytecodeArrayIterator iterator(array); |
378 for (int i = 0; i < kRepeats; i++) { | 377 for (int i = 0; i < kRepeats; i++) { |
379 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 378 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
380 CHECK_EQ(iterator.GetSmi8Operand(0), 2); | 379 CHECK_EQ(iterator.GetImmediateOperand(0), 2); |
381 iterator.Advance(); | 380 iterator.Advance(); |
382 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 381 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
383 CHECK_EQ(iterator.GetSmi8Operand(0), 0); | 382 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
384 iterator.Advance(); | 383 iterator.Advance(); |
385 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 384 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
386 CHECK_EQ(iterator.GetSmi8Operand(0), -2); | 385 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
387 iterator.Advance(); | 386 iterator.Advance(); |
388 } | 387 } |
389 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 388 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
390 iterator.Advance(); | 389 iterator.Advance(); |
391 CHECK(iterator.done()); | 390 CHECK(iterator.done()); |
392 } | 391 } |
393 | 392 |
394 | 393 |
| 394 TEST_F(BytecodeArrayBuilderTest, ToBoolean) { |
| 395 BytecodeArrayBuilder builder(isolate(), zone()); |
| 396 builder.set_parameter_count(0); |
| 397 builder.set_locals_count(0); |
| 398 |
| 399 // Check ToBoolean emitted at start of block. |
| 400 builder.EnterBlock().CastAccumulatorToBoolean(); |
| 401 |
| 402 // Check ToBoolean emitted preceding bytecode is non-boolean. |
| 403 builder.LoadNull().CastAccumulatorToBoolean(); |
| 404 |
| 405 // Check ToBoolean omitted if preceding bytecode is boolean. |
| 406 builder.LoadFalse().CastAccumulatorToBoolean(); |
| 407 |
| 408 // Check ToBoolean emitted if it is at the start of the next block. |
| 409 builder.LoadFalse() |
| 410 .LeaveBlock() |
| 411 .EnterBlock() |
| 412 .CastAccumulatorToBoolean() |
| 413 .LeaveBlock(); |
| 414 |
| 415 builder.Return(); |
| 416 |
| 417 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
| 418 BytecodeArrayIterator iterator(array); |
| 419 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
| 420 iterator.Advance(); |
| 421 |
| 422 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaNull); |
| 423 iterator.Advance(); |
| 424 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
| 425 iterator.Advance(); |
| 426 |
| 427 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); |
| 428 iterator.Advance(); |
| 429 |
| 430 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); |
| 431 iterator.Advance(); |
| 432 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
| 433 iterator.Advance(); |
| 434 |
| 435 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
| 436 iterator.Advance(); |
| 437 CHECK(iterator.done()); |
| 438 } |
| 439 |
| 440 |
395 } // namespace interpreter | 441 } // namespace interpreter |
396 } // namespace internal | 442 } // namespace internal |
397 } // namespace v8 | 443 } // namespace v8 |
OLD | NEW |