| Index: test/cctest/interpreter/generate-bytecode-expectations.cc
|
| diff --git a/test/cctest/interpreter/generate-bytecode-expectations.cc b/test/cctest/interpreter/generate-bytecode-expectations.cc
|
| index 4fc54e12c91010fae925cd30e6ed9ffe0c95f4a3..c055cdc186bf2d59615bc1807570f8722da43084 100644
|
| --- a/test/cctest/interpreter/generate-bytecode-expectations.cc
|
| +++ b/test/cctest/interpreter/generate-bytecode-expectations.cc
|
| @@ -23,6 +23,14 @@ namespace {
|
|
|
| const char* kIndent = " ";
|
|
|
| +enum ConstantPoolType {
|
| + kConstantPoolTypeUnknown,
|
| + kConstantPoolTypeString,
|
| + kConstantPoolTypeInteger,
|
| + kConstantPoolTypeDouble,
|
| + kConstantPoolTypeMixed,
|
| +};
|
| +
|
| class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator {
|
| public:
|
| void* Allocate(size_t length) override {
|
| @@ -121,6 +129,30 @@ i::Handle<v8::internal::BytecodeArray> GetBytecodeArrayForGlobal(
|
| return bytecodes;
|
| }
|
|
|
| +std::string QuoteCString(const std::string& source) {
|
| + std::string quoted_buffer;
|
| + for (char c : source) {
|
| + switch (c) {
|
| + case '"':
|
| + quoted_buffer += "\\\"";
|
| + break;
|
| + case '\n':
|
| + quoted_buffer += "\\n";
|
| + break;
|
| + case '\t':
|
| + quoted_buffer += "\\t";
|
| + break;
|
| + case '\\':
|
| + quoted_buffer += "\\\\";
|
| + break;
|
| + default:
|
| + quoted_buffer += c;
|
| + break;
|
| + }
|
| + }
|
| + return quoted_buffer;
|
| +}
|
| +
|
| void PrintBytecodeOperand(std::ostream& stream,
|
| const BytecodeArrayIterator& bytecode_iter,
|
| const Bytecode& bytecode, int op_index) {
|
| @@ -164,45 +196,55 @@ void PrintBytecode(std::ostream& stream,
|
| }
|
| }
|
|
|
| -std::string QuoteCString(const std::string& source) {
|
| - std::string quoted_buffer;
|
| - for (char c : source) {
|
| - switch (c) {
|
| - case '"':
|
| - quoted_buffer += "\\\"";
|
| - break;
|
| - case '\n':
|
| - quoted_buffer += "\\n";
|
| - break;
|
| - case '\t':
|
| - quoted_buffer += "\\t";
|
| - break;
|
| - case '\\':
|
| - quoted_buffer += "\\\\";
|
| - break;
|
| - default:
|
| - quoted_buffer += c;
|
| - break;
|
| - }
|
| +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));
|
| }
|
| - return quoted_buffer;
|
| + stream << '"';
|
| }
|
|
|
| -void PrintBytecodeArray(std::ostream& stream,
|
| - i::Handle<i::BytecodeArray> bytecode_array,
|
| - const std::string& body, bool print_banner = true) {
|
| - const int kPointerSize = sizeof(void*);
|
| -
|
| - if (print_banner) {
|
| - stream << kIndent << "// === ExpectedSnippet generated by "
|
| - "generate-bytecode-expectations. ===\n";
|
| +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;
|
| + default:
|
| + UNREACHABLE();
|
| + return;
|
| }
|
| +}
|
|
|
| - // Print the code snippet as a quoted C string.
|
| - stream << kIndent << "{" << '"' << QuoteCString(body) << "\",\n" << kIndent;
|
| -
|
| - // Print the frame size, in multiples of kPointerSize.
|
| +void PrintFrameSize(std::ostream& stream,
|
| + i::Handle<i::BytecodeArray> bytecode_array) {
|
| + const int kPointerSize = sizeof(void*);
|
| int frame_size = bytecode_array->frame_size();
|
| +
|
| + stream << kIndent;
|
| +
|
| DCHECK(frame_size % kPointerSize == 0);
|
| if (frame_size > kPointerSize) {
|
| stream << ' ' << frame_size / kPointerSize << " * kPointerSize,\n"
|
| @@ -213,13 +255,15 @@ void PrintBytecodeArray(std::ostream& stream,
|
| stream << " 0,\n" << kIndent;
|
| }
|
|
|
| - // Print parameter count and size of the bytecode array.
|
| - stream << ' ' << bytecode_array->parameter_count() << ",\n"
|
| - << kIndent << ' ' << bytecode_array->length() << ",\n"
|
| + stream << ' ' << bytecode_array->parameter_count() << ",\n";
|
| +}
|
| +
|
| +void PrintBytecodeSequence(std::ostream& stream,
|
| + i::Handle<i::BytecodeArray> bytecode_array) {
|
| + stream << kIndent << ' ' << bytecode_array->length() << ",\n"
|
| << kIndent << " {\n"
|
| << kIndent << " ";
|
|
|
| - // Print bytecodes.
|
| BytecodeArrayIterator bytecode_iter{bytecode_array};
|
| for (; !bytecode_iter.done(); bytecode_iter.Advance()) {
|
| // Print separator before each instruction, except the first one.
|
| @@ -228,13 +272,75 @@ void PrintBytecodeArray(std::ostream& stream,
|
| }
|
| PrintBytecode(stream, bytecode_iter);
|
| }
|
| +}
|
| +
|
| +void PrintConstantPool(std::ostream& stream, i::FixedArray* constant_pool,
|
| + ConstantPoolType expected_constant_type,
|
| + v8::Isolate* isolate) {
|
| + int num_constants = constant_pool->length();
|
| + stream << "\n" << kIndent << " },\n" << kIndent << ' ' << num_constants;
|
| + if (num_constants > 0) {
|
| + stream << ",\n" << kIndent << " {";
|
| + for (int i = 0; i < num_constants; ++i) {
|
| + // Print separator before each constant, except the first one
|
| + if (i != 0) stream << ", ";
|
| + PrintConstant(
|
| + stream, expected_constant_type,
|
| + i::FixedArray::get(constant_pool, i, GetInternalIsolate(isolate)));
|
| + }
|
| + stream << '}';
|
| + }
|
| + stream << '\n';
|
| +}
|
| +
|
| +void PrintBytecodeArray(std::ostream& stream,
|
| + i::Handle<i::BytecodeArray> bytecode_array,
|
| + const std::string& body, v8::Isolate* isolate,
|
| + ConstantPoolType constant_pool_type,
|
| + bool print_banner = true) {
|
| + if (print_banner) {
|
| + stream << kIndent << "// === ExpectedSnippet generated by "
|
| + "generate-bytecode-expectations. ===\n";
|
| + }
|
| +
|
| + // Print the code snippet as a quoted C string.
|
| + stream << kIndent << "{" << '"' << QuoteCString(body) << "\",\n";
|
| +
|
| + 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);
|
|
|
| - stream << "\n" << kIndent << " },\n";
|
| - // TODO(ssanfilippo) add representation of constant pool and handlers.
|
| - stream << kIndent << " // constant pool and handlers here\n";
|
| stream << kIndent << "}\n";
|
| }
|
|
|
| +void PrintExpectedSnippet(ConstantPoolType constant_pool_type, char* exec_path,
|
| + std::string body) {
|
| + const char* wrapper_function_name = "__genbckexp_wrapper__";
|
| +
|
| + V8InitializationScope platform(exec_path);
|
| + {
|
| + v8::Isolate::Scope isolate_scope(platform.isolate());
|
| + v8::HandleScope handle_scope(platform.isolate());
|
| + v8::Local<v8::Context> context = v8::Context::New(platform.isolate());
|
| + v8::Context::Scope context_scope(context);
|
| +
|
| + std::string source_code = WrapCodeInFunction(wrapper_function_name, body);
|
| + CompileAndRun(platform.isolate(), context, source_code.c_str());
|
| +
|
| + i::Handle<i::BytecodeArray> bytecode_array = GetBytecodeArrayForGlobal(
|
| + platform.isolate(), context, wrapper_function_name);
|
| +
|
| + PrintBytecodeArray(std::cout, bytecode_array, body, platform.isolate(),
|
| + constant_pool_type);
|
| + }
|
| +}
|
| +
|
| bool ReadFromFileOrStdin(std::string* body, const char* body_filename) {
|
| std::stringstream body_buffer;
|
| if (strcmp(body_filename, "-") == 0) {
|
| @@ -248,10 +354,24 @@ bool ReadFromFileOrStdin(std::string* body, const char* body_filename) {
|
| return true;
|
| }
|
|
|
| +ConstantPoolType ParseConstantPoolType(const char* type_string) {
|
| + if (strcmp(type_string, "int") == 0) {
|
| + return kConstantPoolTypeInteger;
|
| + } else if (strcmp(type_string, "double") == 0) {
|
| + return kConstantPoolTypeDouble;
|
| + } else if (strcmp(type_string, "string") == 0) {
|
| + return kConstantPoolTypeString;
|
| + } else if (strcmp(type_string, "mixed") == 0) {
|
| + return kConstantPoolTypeMixed;
|
| + }
|
| + return kConstantPoolTypeUnknown;
|
| +}
|
| +
|
| void PrintUsage(const char* exec_path) {
|
| std::cerr << "Usage: " << exec_path
|
| - << " [filename.js|-]\n\n"
|
| - "No arguments or - reads from standard input.\n"
|
| + << " (int|double|string|mixed) [filename.js|-]\n\n"
|
| + "First argument is the type of objects in the constant pool.\n\n"
|
| + "Omitting the second argument or - reads from standard input.\n"
|
| "Anything else is interpreted as a filename.\n\n"
|
| "This tool is intended as a help in writing tests.\n"
|
| "Please, DO NOT blindly copy and paste the output "
|
| @@ -261,13 +381,18 @@ void PrintUsage(const char* exec_path) {
|
| } // namespace
|
|
|
| int main(int argc, char** argv) {
|
| + if (argc < 2) {
|
| + PrintUsage(argv[0]);
|
| + return 1;
|
| + }
|
| +
|
| if (argc > 1 && strcmp(argv[1], "--help") == 0) {
|
| PrintUsage(argv[0]);
|
| return 0;
|
| }
|
|
|
| - const char* body_filename = (argc > 1 ? argv[1] : "-");
|
| - const char* wrapper_function_name = "__genbckexp_wrapper__";
|
| + const char* body_filename = (argc > 2 ? argv[2] : "-");
|
| + const char* const_pool_type_string = argv[1];
|
|
|
| std::string body;
|
| if (!ReadFromFileOrStdin(&body, body_filename)) {
|
| @@ -276,19 +401,6 @@ int main(int argc, char** argv) {
|
| return 1;
|
| }
|
|
|
| - V8InitializationScope platform(argv[0]);
|
| - {
|
| - v8::Isolate::Scope isolate_scope(platform.isolate());
|
| - v8::HandleScope handle_scope(platform.isolate());
|
| - v8::Local<v8::Context> context = v8::Context::New(platform.isolate());
|
| - v8::Context::Scope context_scope(context);
|
| -
|
| - std::string source_code = WrapCodeInFunction(wrapper_function_name, body);
|
| - CompileAndRun(platform.isolate(), context, source_code.c_str());
|
| -
|
| - i::Handle<i::BytecodeArray> bytecode_array = GetBytecodeArrayForGlobal(
|
| - platform.isolate(), context, wrapper_function_name);
|
| -
|
| - PrintBytecodeArray(std::cout, bytecode_array, body);
|
| - }
|
| + PrintExpectedSnippet(ParseConstantPoolType(const_pool_type_string), argv[0],
|
| + body);
|
| }
|
|
|