| 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 |