Commit 00cd9cfd authored by Dan Elphick's avatar Dan Elphick Committed by Commit Bot

[interpreter] Improve reporting for bytecode mismatches

If a bytecode mismatch occurs, the original and new bytecode are now
printed along with the position of the bytecode mismatch.

Bug: v8:8510
Change-Id: Ia3b016fb4e0edde46944533a6a768499b20678d2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1774722
Commit-Queue: Dan Elphick <delphick@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63500}
parent 981aafaf
......@@ -100,9 +100,8 @@ Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) {
}
#ifdef DEBUG
void BytecodeArrayBuilder::CheckBytecodeMatches(
Handle<BytecodeArray> bytecode) {
bytecode_array_writer_.CheckBytecodeMatches(bytecode);
int BytecodeArrayBuilder::CheckBytecodeMatches(Handle<BytecodeArray> bytecode) {
return bytecode_array_writer_.CheckBytecodeMatches(bytecode);
}
#endif
......
......@@ -46,7 +46,7 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
Handle<ByteArray> ToSourcePositionTable(Isolate* isolate);
#ifdef DEBUG
void CheckBytecodeMatches(Handle<BytecodeArray> bytecode);
int CheckBytecodeMatches(Handle<BytecodeArray> bytecode);
#endif
// Get the number of parameters expected by function.
......
......@@ -62,14 +62,27 @@ Handle<ByteArray> BytecodeArrayWriter::ToSourcePositionTable(Isolate* isolate) {
}
#ifdef DEBUG
void BytecodeArrayWriter::CheckBytecodeMatches(Handle<BytecodeArray> bytecode) {
int BytecodeArrayWriter::CheckBytecodeMatches(Handle<BytecodeArray> bytecode) {
int mismatches = false;
int bytecode_size = static_cast<int>(bytecodes()->size());
const byte* bytecode_ptr = &bytecodes()->front();
CHECK_EQ(bytecode_size, bytecode->length());
if (bytecode_size != bytecode->length()) mismatches = true;
// If there's a mismatch only in the length of the bytecode (very unlikely)
// then the first mismatch will be the first extra bytecode.
int first_mismatch = std::min(bytecode_size, bytecode->length());
for (int i = 0; i < first_mismatch; ++i) {
if (bytecode_ptr[i] != bytecode->get(i)) {
mismatches = true;
first_mismatch = i;
break;
}
}
for (int i = 0; i < bytecode_size; ++i) {
CHECK_EQ(bytecode_ptr[i], bytecode->get(i));
if (mismatches) {
return first_mismatch;
}
return -1;
}
#endif
......
......@@ -58,7 +58,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayWriter final {
Handle<ByteArray> ToSourcePositionTable(Isolate* isolate);
#ifdef DEBUG
void CheckBytecodeMatches(Handle<BytecodeArray> bytecode);
// Returns -1 if they match or the offset of the first mismatching byte.
int CheckBytecodeMatches(Handle<BytecodeArray> bytecode);
#endif
bool RemainderOfBlockIsDead() const { return exit_seen_in_block_; }
......
......@@ -1074,8 +1074,6 @@ Handle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
// Unoptimized compilation should be context-independent. Verify that we don't
// access the native context by nulling it out during finalization.
NullContextScope null_context_scope(isolate);
builder()->CheckBytecodeMatches(info_->bytecode_array());
#endif
Handle<ByteArray> source_position_table =
......@@ -1089,6 +1087,12 @@ Handle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
return source_position_table;
}
#ifdef DEBUG
int BytecodeGenerator::CheckBytecodeMatches(Handle<BytecodeArray> bytecode) {
return builder()->CheckBytecodeMatches(bytecode);
}
#endif
void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
Handle<Script> script) {
// Build global declaration pair arrays.
......
......@@ -41,6 +41,10 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
Handle<Script> script);
Handle<ByteArray> FinalizeSourcePositionTable(Isolate* isolate);
#ifdef DEBUG
int CheckBytecodeMatches(Handle<BytecodeArray> bytecode);
#endif
#define DECLARE_VISIT(type) void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
......
......@@ -9,6 +9,7 @@
#include "builtins-generated/bytecodes-builtins-list.h"
#include "src/ast/prettyprinter.h"
#include "src/ast/scopes.h"
#include "src/codegen/compiler.h"
#include "src/codegen/unoptimized-compilation-info.h"
#include "src/init/bootstrapper.h"
......@@ -42,6 +43,8 @@ class InterpreterCompilationJob final : public UnoptimizedCompilationJob {
private:
BytecodeGenerator* generator() { return &generator_; }
void CheckAndPrintBytecodeMismatch(Isolate* isolate,
Handle<BytecodeArray> bytecode);
Zone zone_;
UnoptimizedCompilationInfo compilation_info_;
......@@ -202,6 +205,25 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::ExecuteJobImpl() {
return SUCCEEDED;
}
#ifdef DEBUG
void InterpreterCompilationJob::CheckAndPrintBytecodeMismatch(
Isolate* isolate, Handle<BytecodeArray> bytecode) {
int first_mismatch = generator()->CheckBytecodeMatches(bytecode);
if (first_mismatch >= 0) {
parse_info()->ast_value_factory()->Internalize(isolate);
DeclarationScope::AllocateScopeInfos(parse_info(), isolate);
Handle<BytecodeArray> new_bytecode =
generator()->FinalizeBytecode(isolate, parse_info()->script());
std::cerr << "Bytecode mismatch\nOriginal bytecode:\n";
bytecode->Disassemble(std::cerr);
std::cerr << "\nNew bytecode:\n";
new_bytecode->Disassemble(std::cerr);
FATAL("Bytecode mismatch at offset %d\n", first_mismatch);
}
}
#endif
InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
RuntimeCallTimerScope runtimeTimerScope(
......@@ -236,6 +258,10 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
os << std::flush;
}
#ifdef DEBUG
CheckAndPrintBytecodeMismatch(isolate, bytecodes);
#endif
return SUCCEEDED;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment