Commit d7ea6030 authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Avoid creating temporary source position table.

This changes the WebAssembly pipeline to no longer expect source
position tables for {WasmCode} to be allocated on the GC'ed heap.

R=clemensh@chromium.org
BUG=v8:7721

Change-Id: Ib2c6e3d0840e47b83809f60519c0d1b94af186af
Reviewed-on: https://chromium-review.googlesource.com/1109686
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53961}
parent be9fd5b1
......@@ -378,8 +378,8 @@ void CodeGenerator::AssembleArchBinarySearchSwitchRange(
AssembleArchBinarySearchSwitchRange(input, def_block, begin, middle);
}
Handle<ByteArray> CodeGenerator::GetSourcePositionTable() {
return source_position_table_builder_.ToSourcePositionTable(isolate());
OwnedVector<byte> CodeGenerator::GetSourcePositionTable() {
return source_position_table_builder_.ToSourcePositionTableVector();
}
MaybeHandle<Code> CodeGenerator::FinalizeCode() {
......
......@@ -92,7 +92,7 @@ class CodeGenerator final : public GapResolver::Assembler {
void AssembleCode(); // Does not need to run on main thread.
MaybeHandle<Code> FinalizeCode();
Handle<ByteArray> GetSourcePositionTable();
OwnedVector<byte> GetSourcePositionTable();
InstructionSequence* code() const { return code_; }
FrameAccessState* frame_access_state() const { return frame_access_state_; }
......
......@@ -111,6 +111,22 @@ Vector<const byte> VectorFromByteArray(ByteArray* byte_array) {
byte_array->length());
}
#ifdef ENABLE_SLOW_DCHECKS
void CheckTableEquals(std::vector<PositionTableEntry>& raw_entries,
SourcePositionTableIterator& encoded) {
// Brute force testing: Record all positions and decode
// the entire table to verify they are identical.
auto raw = raw_entries.begin();
for (; !encoded.done(); encoded.Advance(), raw++) {
DCHECK(raw != raw_entries.end());
DCHECK_EQ(encoded.code_offset(), raw->code_offset);
DCHECK_EQ(encoded.source_position().raw(), raw->source_position);
DCHECK_EQ(encoded.is_statement(), raw->is_statement);
}
DCHECK(raw == raw_entries.end());
}
#endif
} // namespace
SourcePositionTableBuilder::SourcePositionTableBuilder(
......@@ -143,21 +159,31 @@ Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable(
Handle<ByteArray> table = isolate->factory()->NewByteArray(
static_cast<int>(bytes_.size()), TENURED);
MemCopy(table->GetDataStartAddress(), bytes_.data(), bytes_.size());
MemCopy(table->GetDataStartAddress(), &*bytes_.begin(), bytes_.size());
#ifdef ENABLE_SLOW_DCHECKS
// Brute force testing: Record all positions and decode
// the entire table to verify they are identical.
SourcePositionTableIterator it(*table);
CheckTableEquals(raw_entries_, it);
// No additional source positions after creating the table.
mode_ = OMIT_SOURCE_POSITIONS;
#endif
return table;
}
OwnedVector<byte> SourcePositionTableBuilder::ToSourcePositionTableVector() {
if (bytes_.empty()) return OwnedVector<byte>();
DCHECK(!Omit());
OwnedVector<byte> table = OwnedVector<byte>::New(bytes_.size());
MemCopy(table.start(), bytes_.data(), bytes_.size());
#ifdef ENABLE_SLOW_DCHECKS
// Brute force testing: Record all positions and decode
// the entire table to verify they are identical.
auto raw = raw_entries_.begin();
for (SourcePositionTableIterator encoded(*table); !encoded.done();
encoded.Advance(), raw++) {
DCHECK(raw != raw_entries_.end());
DCHECK_EQ(encoded.code_offset(), raw->code_offset);
DCHECK_EQ(encoded.source_position().raw(), raw->source_position);
DCHECK_EQ(encoded.is_statement(), raw->is_statement);
}
DCHECK(raw == raw_entries_.end());
SourcePositionTableIterator it(table.as_vector());
CheckTableEquals(raw_entries_, it);
// No additional source positions after creating the table.
mode_ = OMIT_SOURCE_POSITIONS;
#endif
......
......@@ -42,6 +42,7 @@ class V8_EXPORT_PRIVATE SourcePositionTableBuilder {
bool is_statement);
Handle<ByteArray> ToSourcePositionTable(Isolate* isolate);
OwnedVector<byte> ToSourcePositionTableVector();
private:
void AddEntry(const PositionTableEntry& entry);
......
......@@ -183,6 +183,43 @@ class ScopedVector : public Vector<T> {
DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedVector);
};
template <typename T>
class OwnedVector {
public:
MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(OwnedVector);
OwnedVector(std::unique_ptr<T[]> data, size_t length)
: data_(std::move(data)), length_(length) {
DCHECK_IMPLIES(length_ > 0, data_ != nullptr);
}
// Returns the length of the vector as a size_t.
constexpr size_t size() const { return length_; }
// Returns whether or not the vector is empty.
constexpr bool is_empty() const { return length_ == 0; }
// Returns the pointer to the start of the data in the vector.
T* start() const {
DCHECK_IMPLIES(length_ > 0, data_ != nullptr);
return data_.get();
}
// Returns a {Vector<T>} view of the data in this vector.
Vector<T> as_vector() const { return Vector<T>(start(), size()); }
// Releases the backing data from this vector and transfers ownership to the
// caller. This vectors data can no longer be used afterwards.
std::unique_ptr<T[]> ReleaseData() { return std::move(data_); }
// Allocates a new vector of the specified size via the default allocator.
static OwnedVector<T> New(size_t size) {
return OwnedVector<T>(std::unique_ptr<T[]>(new T[size]), size);
}
private:
std::unique_ptr<T[]> data_;
size_t length_ = 0;
};
inline int StrLength(const char* string) {
size_t length = strlen(string);
......
......@@ -1874,14 +1874,13 @@ wasm::WasmCode* LiftoffCompilationUnit::FinishCompilation(
CodeDesc desc;
asm_.GetCode(wasm_unit_->isolate_, &desc);
Handle<ByteArray> source_positions =
source_position_table_builder_.ToSourcePositionTable(
wasm_unit_->isolate_);
OwnedVector<byte> source_positions =
source_position_table_builder_.ToSourcePositionTableVector();
wasm::WasmCode* code = wasm_unit_->native_module_->AddCode(
desc, asm_.GetTotalFrameSlotCount(), wasm_unit_->func_index_,
safepoint_table_offset_, 0, std::move(protected_instructions_),
source_positions, wasm::WasmCode::kLiftoff);
std::move(source_positions), wasm::WasmCode::kLiftoff);
return code;
}
......
......@@ -525,25 +525,19 @@ WasmCode* NativeModule::AddCode(
const CodeDesc& desc, uint32_t frame_slots, uint32_t index,
size_t safepoint_table_offset, size_t handler_table_offset,
std::unique_ptr<ProtectedInstructions> protected_instructions,
Handle<ByteArray> source_pos_table, WasmCode::Tier tier) {
OwnedVector<byte> source_pos_table, WasmCode::Tier tier) {
std::unique_ptr<byte[]> reloc_info;
if (desc.reloc_size) {
reloc_info.reset(new byte[desc.reloc_size]);
memcpy(reloc_info.get(), desc.buffer + desc.buffer_size - desc.reloc_size,
desc.reloc_size);
}
std::unique_ptr<byte[]> source_pos;
if (source_pos_table->length() > 0) {
source_pos.reset(new byte[source_pos_table->length()]);
source_pos_table->copy_out(0, source_pos.get(), source_pos_table->length());
}
WasmCode* ret = AddOwnedCode(
{desc.buffer, static_cast<size_t>(desc.instr_size)},
std::move(reloc_info), static_cast<size_t>(desc.reloc_size),
std::move(source_pos), static_cast<size_t>(source_pos_table->length()),
Just(index), WasmCode::kFunction,
desc.instr_size - desc.constant_pool_size, frame_slots,
safepoint_table_offset, handler_table_offset,
source_pos_table.ReleaseData(), source_pos_table.size(), Just(index),
WasmCode::kFunction, desc.instr_size - desc.constant_pool_size,
frame_slots, safepoint_table_offset, handler_table_offset,
std::move(protected_instructions), tier, WasmCode::kNoFlushICache);
// Apply the relocation delta by iterating over the RelocInfo.
......@@ -579,7 +573,7 @@ WasmCode* NativeModule::AddCode(
ret->instructions().size());
if (FLAG_print_code || FLAG_print_wasm_code) {
// TODO(mstarzinger): don't need the isolate here.
ret->Print(source_pos_table->GetIsolate());
ret->Print(module_object()->GetIsolate());
}
ret->Validate();
return ret;
......
......@@ -239,7 +239,7 @@ class V8_EXPORT_PRIVATE NativeModule final {
WasmCode* AddCode(const CodeDesc& desc, uint32_t frame_count, uint32_t index,
size_t safepoint_table_offset, size_t handler_table_offset,
std::unique_ptr<ProtectedInstructions>,
Handle<ByteArray> source_position_table,
OwnedVector<byte> source_position_table,
WasmCode::Tier tier);
// A way to copy over JS-allocated code. This is because we compile
......
......@@ -3438,13 +3438,11 @@ TEST(Liftoff_tier_up) {
memcpy(buffer.get(), sub_code->instructions().start(), sub_size);
desc.buffer = buffer.get();
desc.instr_size = static_cast<int>(sub_size);
Isolate* isolate = CcTest::InitIsolateOnce();
Handle<ByteArray> source_pos = isolate->factory()->empty_byte_array();
std::unique_ptr<ProtectedInstructions> protected_instructions(
new ProtectedInstructions(sub_code->protected_instructions()));
native_module->AddCode(desc, 0, add.function_index(), 0, 0,
std::move(protected_instructions), source_pos,
WasmCode::kOther);
std::move(protected_instructions),
OwnedVector<byte>(), WasmCode::kOther);
// Second run should now execute {sub}.
CHECK_EQ(4, r.Call(11, 7));
......
......@@ -176,8 +176,7 @@ class WasmCodeManagerTest : public TestWithContext,
std::unique_ptr<byte[]> exec_buff(new byte[size]);
desc.buffer = exec_buff.get();
desc.instr_size = static_cast<int>(size);
Handle<ByteArray> source_pos = i_isolate()->factory()->empty_byte_array();
return native_module->AddCode(desc, 0, index, 0, 0, {}, source_pos,
return native_module->AddCode(desc, 0, index, 0, 0, {}, OwnedVector<byte>(),
WasmCode::kOther);
}
......
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