Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Unified Diff: test/cctest/interpreter/bytecode-expectations.cc

Issue 1688383003: [Interpreter] Change the output format of generate-bytecode-expectations. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix help message. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: test/cctest/interpreter/bytecode-expectations.cc
diff --git a/test/cctest/interpreter/bytecode-expectations.cc b/test/cctest/interpreter/bytecode-expectations.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0fcff5761b0b6d983887b23ed8a9dd994d0372da
--- /dev/null
+++ b/test/cctest/interpreter/bytecode-expectations.cc
@@ -0,0 +1,276 @@
+// Copyright 2016 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 "test/cctest/interpreter/bytecode-expectations.h"
+
+#include <iostream>
+
+#include "include/libplatform/libplatform.h"
+#include "include/v8.h"
+
+#include "src/base/logging.h"
+#include "src/base/smart-pointers.h"
+#include "src/compiler.h"
+
+#include "src/interpreter/bytecode-array-iterator.h"
+#include "src/interpreter/bytecode-generator.h"
+#include "src/interpreter/bytecodes.h"
+#include "src/interpreter/interpreter.h"
+
+using namespace v8::internal::interpreter;
+
+namespace {
+
+i::Isolate* GetInternalIsolate(v8::Isolate* isolate) {
rmcilroy 2016/02/12 15:29:05 Move this to generate-bytecode-expectations.cc and
Stefano Sanfilippo 2016/02/12 18:29:40 Turns out we need the external Isolate as well, fo
rmcilroy 2016/02/15 11:15:19 What you've done here is fine (modulo the rename o
+ return reinterpret_cast<i::Isolate*>(isolate);
+}
+
+v8::Local<v8::String> V8StringFromUTF8(v8::Isolate* isolate, const char* data) {
+ return v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal)
+ .ToLocalChecked();
+}
+
+std::string WrapCodeInFunction(const char* function_name,
+ const std::string& function_body) {
+ std::ostringstream program_stream;
+ program_stream << "function " << function_name << "() {" << function_body
+ << "}\n"
+ << function_name << "();";
+
+ return program_stream.str();
+}
+
+v8::Local<v8::Value> CompileAndRun(v8::Isolate* isolate, const char* program) {
+ v8::Local<v8::String> source = V8StringFromUTF8(isolate, program);
+ v8::Local<v8::Script> script =
+ v8::Script::Compile(isolate->GetCurrentContext(), source)
+ .ToLocalChecked();
+
+ v8::Local<v8::Value> result;
+ CHECK(script->Run(isolate->GetCurrentContext()).ToLocal(&result));
+
+ return result;
+}
+
+i::Handle<v8::internal::BytecodeArray> GetBytecodeArrayForGlobal(
+ v8::Isolate* isolate, const char* global_name) {
+ const v8::Local<v8::Context>& context = isolate->GetCurrentContext();
+ v8::Local<v8::String> v8_global_name = V8StringFromUTF8(isolate, global_name);
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+ context->Global()->Get(context, v8_global_name).ToLocalChecked());
+ i::Handle<i::JSFunction> js_function =
+ i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function));
+
+ i::Handle<i::BytecodeArray> bytecodes = i::handle(
+ js_function->shared()->bytecode_array(), GetInternalIsolate(isolate));
+
+ return bytecodes;
+}
+
+void PrintEscapedString(std::ostream& stream, const std::string& string) {
+ for (char c : string) {
+ switch (c) {
+ case '"':
+ stream << "\\\"";
+ break;
+ case '\\':
+ stream << "\\\\";
+ break;
+ default:
+ stream << c;
+ break;
+ }
+ }
+}
+
+void PrintBytecodeOperand(std::ostream& stream,
rmcilroy 2016/02/12 15:29:05 Functions from here onwards should be private func
Stefano Sanfilippo 2016/02/12 18:29:40 Done.
+ const BytecodeArrayIterator& bytecode_iter,
+ const Bytecode& bytecode, int op_index) {
+ OperandType op_type = Bytecodes::GetOperandType(bytecode, op_index);
+ OperandSize op_size = Bytecodes::GetOperandSize(bytecode, op_index);
+
+ const char* size_tag;
+ switch (op_size) {
+ case OperandSize::kByte:
+ size_tag = "8";
+ break;
+ case OperandSize::kShort:
+ size_tag = "16";
+ break;
+ default:
+ UNREACHABLE();
+ return;
+ }
+
+ if (Bytecodes::IsRegisterOperandType(op_type)) {
+ Register register_value = bytecode_iter.GetRegisterOperand(op_index);
+ stream << 'R';
+ if (op_size != OperandSize::kByte) stream << size_tag;
+ stream << '(' << register_value.index() << ')';
+ } else {
+ stream << 'U' << size_tag << '(';
+
+ if (Bytecodes::IsImmediateOperandType(op_type)) {
+ // We need a cast, otherwise the result is printed as char.
+ stream << static_cast<int>(bytecode_iter.GetImmediateOperand(op_index));
+ } else if (Bytecodes::IsRegisterCountOperandType(op_type)) {
+ stream << bytecode_iter.GetRegisterCountOperand(op_index);
+ } else if (Bytecodes::IsIndexOperandType(op_type)) {
+ stream << bytecode_iter.GetIndexOperand(op_index);
+ } else {
+ UNREACHABLE();
+ }
+
+ stream << ')';
+ }
+}
+
+void PrintBytecode(std::ostream& stream,
+ const BytecodeArrayIterator& bytecode_iter) {
+ Bytecode bytecode = bytecode_iter.current_bytecode();
+
+ stream << "B(" << Bytecodes::ToString(bytecode) << ')';
+
+ int operands_count = Bytecodes::NumberOfOperands(bytecode);
+ for (int op_index = 0; op_index < operands_count; ++op_index) {
+ stream << ", ";
+ PrintBytecodeOperand(stream, bytecode_iter, bytecode, op_index);
+ }
+}
+
+void PrintV8String(std::ostream& stream, i::String* string) {
+ stream << '"';
+ for (int i = 0, length = string->length(); i < length; ++i) {
+ stream << i::AsEscapedUC16ForJSON(string->Get(i));
+ }
+ stream << '"';
+}
+
+void PrintConstant(std::ostream& stream,
+ ConstantPoolType expected_constant_type,
+ i::Handle<i::Object> constant) {
+ switch (expected_constant_type) {
+ case kConstantPoolTypeString:
+ CHECK(constant->IsString());
+ PrintV8String(stream, i::String::cast(*constant));
+ break;
+ case kConstantPoolTypeInteger:
+ if (constant->IsSmi()) {
+ i::Smi::cast(*constant)->SmiPrint(stream);
+ } else if (constant->IsHeapNumber()) {
+ i::HeapNumber::cast(*constant)->HeapNumberPrint(stream);
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ case kConstantPoolTypeDouble:
+ i::HeapNumber::cast(*constant)->HeapNumberPrint(stream);
+ break;
+ case kConstantPoolTypeMixed:
+ if (constant->IsSmi()) {
+ stream << "kInstanceTypeDontCare";
+ } else {
+ stream << "InstanceType::"
+ << i::HeapObject::cast(*constant)->map()->instance_type();
+ }
+ break;
+ case kConstantPoolTypeUnknown:
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void PrintFrameSize(std::ostream& stream,
+ i::Handle<i::BytecodeArray> bytecode_array) {
+ const int kPointerSize = sizeof(void*);
+ int frame_size = bytecode_array->frame_size();
+
+ DCHECK_EQ(frame_size % kPointerSize, 0);
+ stream << "frame size: " << frame_size / kPointerSize;
+ if (frame_size > 0) stream << " # in multiples of sizeof(void*)";
+ stream << "\nparameter count: " << bytecode_array->parameter_count() << '\n';
+}
+
+void PrintBytecodeSequence(std::ostream& stream,
+ i::Handle<i::BytecodeArray> bytecode_array) {
+ stream << "bytecodes: [\n";
+ BytecodeArrayIterator bytecode_iter{bytecode_array};
+ for (; !bytecode_iter.done(); bytecode_iter.Advance()) {
+ stream << " ";
+ PrintBytecode(stream, bytecode_iter);
+ stream << ",\n";
+ }
+ stream << "]\n";
+}
+
+void PrintConstantPool(std::ostream& stream, i::FixedArray* constant_pool,
+ ConstantPoolType const_pool_type, v8::Isolate* isolate) {
+ stream << "constant pool: [\n";
+ int num_constants = constant_pool->length();
+ if (num_constants > 0) {
+ for (int i = 0; i < num_constants; ++i) {
+ stream << " ";
+ PrintConstant(
+ stream, const_pool_type,
+ i::FixedArray::get(constant_pool, i, GetInternalIsolate(isolate)));
+ stream << ",\n";
+ }
+ }
+ stream << "]\n";
+}
+
+void PrintCodeSnippet(std::ostream& stream, const std::string& body) {
+ stream << "snippet: \"\n";
+ std::stringstream body_stream{body};
+ std::string body_line;
+ while (std::getline(body_stream, body_line)) {
+ stream << " ";
+ PrintEscapedString(stream, body_line);
+ stream << '\n';
+ }
+ stream << "\"\n";
+}
+
+void PrintBytecodeArray(std::ostream& stream,
+ i::Handle<i::BytecodeArray> bytecode_array,
+ const std::string& body, v8::Isolate* isolate,
+ ConstantPoolType constant_pool_type) {
+ stream << "---\n";
+ PrintCodeSnippet(stream, body);
+ PrintFrameSize(stream, bytecode_array);
+ PrintBytecodeSequence(stream, bytecode_array);
+ PrintConstantPool(stream, bytecode_array->constant_pool(), constant_pool_type,
+ isolate);
+
+ // TODO(ssanfilippo) print handlers.
+ i::HandlerTable* handlers =
+ i::HandlerTable::cast(bytecode_array->handler_table());
+ CHECK_EQ(handlers->NumberOfRangeEntries(), 0);
+}
+
+} // namespace
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+void ExpectationPrinter::PrintExpectation(std::ostream& stream,
+ const std::string& snippet) {
+ const char* wrapper_function_name = "__genbckexp_wrapper__";
+
+ std::string source_code = WrapCodeInFunction(wrapper_function_name, snippet);
+ CompileAndRun(isolate_, source_code.c_str());
+
+ i::Handle<i::BytecodeArray> bytecode_array =
+ GetBytecodeArrayForGlobal(isolate_, wrapper_function_name);
+
+ PrintBytecodeArray(stream, bytecode_array, snippet, isolate_,
+ const_pool_type_);
+ stream << '\n';
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8

Powered by Google App Engine
This is Rietveld 408576698