Index: test/cctest/interpreter/test-bytecode-generator.cc |
diff --git a/test/cctest/interpreter/test-bytecode-generator.cc b/test/cctest/interpreter/test-bytecode-generator.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..deb6c971a1d3d91a7ef13bad798cd6c629683350 |
--- /dev/null |
+++ b/test/cctest/interpreter/test-bytecode-generator.cc |
@@ -0,0 +1,129 @@ |
+// Copyright 2015 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/compiler.h" |
+#include "src/interpreter/bytecode-generator.h" |
+#include "src/interpreter/interpreter.h" |
+#include "test/cctest/cctest.h" |
+ |
+namespace v8 { |
+namespace internal { |
+namespace interpreter { |
+ |
+class BytecodeGeneratorHelper { |
+ public: |
+ const char* kFunctionName = "my_function"; |
+ |
+ BytecodeGeneratorHelper() { |
+ i::FLAG_ignition = true; |
+ i::FLAG_ignition_filter = kFunctionName; |
+ CcTest::i_isolate()->interpreter()->Initialize(); |
+ } |
+ |
+ |
+ Handle<BytecodeArray> MakeBytecode(const char* script, |
+ const char* function_name) { |
+ CompileRun(script); |
+ Local<Function> function = |
+ Local<Function>::Cast(CcTest::global()->Get(v8_str(function_name))); |
+ i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*function); |
+ return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); |
+ } |
+ |
+ |
+ Handle<BytecodeArray> MakeBytecodeForFunctionBody(const char* body) { |
+ ScopedVector<char> program(1024); |
+ SNPrintF(program, "function %s() { %s }\n%s();", kFunctionName, body, |
+ kFunctionName); |
+ return MakeBytecode(program.start(), kFunctionName); |
+ } |
+}; |
+ |
+ |
+// Structure for containing expected bytecode snippets. |
+struct ExpectedSnippet { |
+ const char* body; |
+ int frame_size; |
+ int bytecode_length; |
+ const uint8_t bytecode[16]; |
+}; |
+ |
+ |
+// Helper macros for handcrafting bytecode sequences. |
+#define B(x) static_cast<uint8_t>(Bytecode::k##x) |
+#define U8(x) static_cast<uint8_t>(x & 0xff) |
+#define R(x) static_cast<uint8_t>(-x & 0xff) |
+ |
+ |
+TEST(PrimitiveReturnStatements) { |
+ InitializedHandleScope handle_scope; |
+ BytecodeGeneratorHelper helper; |
+ |
+ ExpectedSnippet snippets[] = { |
+ {"return;", 0, 2, {B(LdaUndefined), B(Return)}}, |
+ {"return null;", 0, 2, {B(LdaNull), B(Return)}}, |
+ {"return true;", 0, 2, {B(LdaTrue), B(Return)}}, |
+ {"return false;", 0, 2, {B(LdaFalse), B(Return)}}, |
+ {"return 0;", 0, 2, {B(LdaZero), B(Return)}}, |
+ {"return +1;", 0, 3, {B(LdaSmi8), U8(1), B(Return)}}, |
+ {"return -1;", 0, 3, {B(LdaSmi8), U8(-1), B(Return)}}, |
+ {"return +127;", 0, 3, {B(LdaSmi8), U8(127), B(Return)}}, |
+ {"return -128;", 0, 3, {B(LdaSmi8), U8(-128), B(Return)}}, |
+ }; |
+ |
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
+ for (size_t i = 0; i < num_snippets; i++) { |
+ Handle<BytecodeArray> ba = |
+ helper.MakeBytecodeForFunctionBody(snippets[i].body); |
+ CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
+ CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
+ CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
+ ba->length())); |
+ } |
+} |
+ |
+ |
+TEST(PrimitiveExpressions) { |
+ InitializedHandleScope handle_scope; |
+ BytecodeGeneratorHelper helper; |
+ |
+ ExpectedSnippet snippets[] = { |
+ {"var x = 0; return x;", |
+ kPointerSize, |
+ 6, |
+ { |
+ B(LdaZero), // |
+ B(Star), R(0), // |
+ B(Ldar), R(0), // |
+ B(Return) // |
+ }}, |
+ {"var x = 0; return x + 3;", |
+ 2 * kPointerSize, |
+ 12, |
+ { |
+ B(LdaZero), // |
+ B(Star), R(0), // |
+ B(Ldar), R(0), // Easy to spot r1 not really needed here. |
+ B(Star), R(1), // Dead store. |
+ B(LdaSmi8), U8(3), // |
+ B(Add), R(1), // |
+ B(Return) // |
+ }}}; |
+ |
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
+ for (size_t i = 0; i < num_snippets; i++) { |
+ Handle<BytecodeArray> ba = |
+ helper.MakeBytecodeForFunctionBody(snippets[i].body); |
+ CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
+ CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
+ CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
+ ba->length())); |
+ } |
+} |
+ |
+} // namespace interpreter |
+} // namespace internal |
+} // namespance v8 |