| Index: test/cctest/interpreter/test-bytecode-array-builder.cc
|
| diff --git a/test/cctest/interpreter/test-bytecode-array-builder.cc b/test/cctest/interpreter/test-bytecode-array-builder.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0fe7f61e6ddb99cd4c5c249b7c1defaa8ff028f8
|
| --- /dev/null
|
| +++ b/test/cctest/interpreter/test-bytecode-array-builder.cc
|
| @@ -0,0 +1,112 @@
|
| +// Copyright 2014 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "src/v8.h"
|
| +
|
| +#include "src/interpreter/bytecode-array-builder.h"
|
| +#include "test/cctest/cctest.h"
|
| +
|
| +using namespace v8::internal;
|
| +using namespace v8::internal::interpreter;
|
| +
|
| +TEST(AllBytecodesGenerated) {
|
| + InitializedHandleScope handle_scope;
|
| + BytecodeArrayBuilder builder(handle_scope.main_isolate());
|
| +
|
| + builder.set_locals_count(1);
|
| + CHECK_EQ(builder.locals_count(), 1);
|
| +
|
| + // Emit constant loads.
|
| + builder.LoadLiteral(Smi::FromInt(0))
|
| + .LoadLiteral(Smi::FromInt(8))
|
| + .LoadUndefined()
|
| + .LoadNull()
|
| + .LoadTheHole()
|
| + .LoadTrue()
|
| + .LoadFalse();
|
| +
|
| + // Emit accumulator transfers.
|
| + builder.LoadAccumulatorWithRegister(0).StoreAccumulatorInRegister(0);
|
| +
|
| + // Emit binary operators invocations.
|
| + builder.BinaryOperation(Token::Value::ADD, 0)
|
| + .BinaryOperation(Token::Value::SUB, 0)
|
| + .BinaryOperation(Token::Value::MUL, 0)
|
| + .BinaryOperation(Token::Value::DIV, 0);
|
| +
|
| + // Emit control flow. Return must be the last instruction.
|
| + builder.Return();
|
| +
|
| + // Generate BytecodeArray.
|
| + Handle<BytecodeArray> the_array = builder.ToBytecodeArray();
|
| + CHECK_EQ(the_array->frame_size(), builder.locals_count() * kPointerSize);
|
| +
|
| + // Build scorecard of bytecodes encountered in the BytecodeArray.
|
| + std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1);
|
| + Bytecode final_bytecode = Bytecode::kLdaZero;
|
| + for (int i = 0; i < the_array->length(); i++) {
|
| + uint8_t code = the_array->get(i);
|
| + scorecard[code] += 1;
|
| + int operands = Bytecodes::NumberOfOperands(Bytecodes::FromByte(code));
|
| + CHECK_LE(operands, Bytecodes::MaximumNumberOfOperands());
|
| + final_bytecode = Bytecodes::FromByte(code);
|
| + i += operands;
|
| + }
|
| +
|
| + // Check return occurs at the end and only once in the BytecodeArray.
|
| + CHECK_EQ(final_bytecode, Bytecode::kReturn);
|
| + CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
|
| +
|
| +#define CHECK_BYTECODE_PRESENT(Name, ...) \
|
| + /* Check Bytecode is marked in scorecard */ \
|
| + CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1);
|
| + BYTECODE_LIST(CHECK_BYTECODE_PRESENT)
|
| +#undef CHECK_BYTECODE_PRESENT
|
| +}
|
| +
|
| +
|
| +TEST(FrameSizesLookGood) {
|
| + for (int locals = 1; locals < 5; locals++) {
|
| + for (int temps = 0; temps < 3; temps++) {
|
| + InitializedHandleScope handle_scope;
|
| + BytecodeArrayBuilder builder(handle_scope.main_isolate());
|
| + builder.set_locals_count(locals);
|
| + builder.Return();
|
| +
|
| + TemporaryRegisterScope temporaries(&builder);
|
| + for (int i = 0; i < temps; i++) {
|
| + temporaries.NewRegister();
|
| + }
|
| +
|
| + Handle<BytecodeArray> the_array = builder.ToBytecodeArray();
|
| + int total_registers = locals + temps;
|
| + CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(TemporariesRecycled) {
|
| + InitializedHandleScope handle_scope;
|
| + BytecodeArrayBuilder builder(handle_scope.main_isolate());
|
| + builder.set_locals_count(0);
|
| + builder.Return();
|
| +
|
| + int first;
|
| + {
|
| + TemporaryRegisterScope temporaries(&builder);
|
| + first = temporaries.NewRegister();
|
| + temporaries.NewRegister();
|
| + temporaries.NewRegister();
|
| + temporaries.NewRegister();
|
| + }
|
| +
|
| + int second;
|
| + {
|
| + TemporaryRegisterScope temporaries(&builder);
|
| + second = temporaries.NewRegister();
|
| + }
|
| +
|
| + CHECK_EQ(first, second);
|
| +}
|
|
|