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

Unified Diff: runtime/vm/deopt_instructions.cc

Issue 1054393003: Compress deopt instructions in memory using variable length encoding. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: landing Created 5 years, 8 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
« no previous file with comments | « runtime/vm/deopt_instructions.h ('k') | runtime/vm/flow_graph_compiler.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/deopt_instructions.cc
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 34612cd89c13e634ab79daec99a7afeafb535b02..401f2ba4d995fbfe1ddae14272c1732756ee1eb8 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -28,7 +28,7 @@ DeoptContext::DeoptContext(const StackFrame* frame,
intptr_t* cpu_registers)
: code_(code.raw()),
object_table_(code.object_table()),
- deopt_info_(DeoptInfo::null()),
+ deopt_info_(TypedData::null()),
dest_frame_is_allocated_(false),
dest_frame_(NULL),
dest_frame_size_(0),
@@ -44,7 +44,7 @@ DeoptContext::DeoptContext(const StackFrame* frame,
deferred_slots_(NULL),
deferred_objects_count_(0),
deferred_objects_(NULL) {
- const DeoptInfo& deopt_info = DeoptInfo::Handle(
+ const TypedData& deopt_info = TypedData::Handle(
code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason_, &deopt_flags_));
ASSERT(!deopt_info.IsNull());
deopt_info_ = deopt_info.raw();
@@ -81,7 +81,7 @@ DeoptContext::DeoptContext(const StackFrame* frame,
}
caller_fp_ = GetSourceFp();
- dest_frame_size_ = deopt_info.FrameSize();
+ dest_frame_size_ = DeoptInfo::FrameSize(deopt_info);
if (dest_options == kDestIsAllocated) {
dest_frame_ = new intptr_t[dest_frame_size_];
@@ -204,7 +204,6 @@ static bool IsObjectInstruction(DeoptInstr::Kind kind) {
case DeoptInstr::kCallerPc:
return false;
- case DeoptInstr::kSuffix:
case DeoptInstr::kMaterializeObject:
default:
// We should not encounter these instructions when filling stack slots.
@@ -218,15 +217,15 @@ static bool IsObjectInstruction(DeoptInstr::Kind kind) {
void DeoptContext::FillDestFrame() {
const Code& code = Code::Handle(code_);
- const DeoptInfo& deopt_info = DeoptInfo::Handle(deopt_info_);
+ const TypedData& deopt_info = TypedData::Handle(deopt_info_);
- const intptr_t len = deopt_info.TranslationLength();
- GrowableArray<DeoptInstr*> deopt_instructions(len);
+ GrowableArray<DeoptInstr*> deopt_instructions;
const Array& deopt_table = Array::Handle(code.deopt_info_array());
ASSERT(!deopt_table.IsNull());
- deopt_info.ToInstructions(deopt_table, &deopt_instructions);
+ DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions);
- const intptr_t frame_size = deopt_info.FrameSize();
+ const intptr_t len = deopt_instructions.length();
+ const intptr_t frame_size = dest_frame_size_;
// For now, we never place non-objects in the deoptimized frame if
// the destination frame is a copy. This allows us to copy the
@@ -241,7 +240,8 @@ void DeoptContext::FillDestFrame() {
// described as part of the expression stack for the bottom-most deoptimized
// frame. They will be used during materialization and removed from the stack
// right before control switches to the unoptimized code.
- const intptr_t num_materializations = deopt_info.NumMaterializations();
+ const intptr_t num_materializations =
+ DeoptInfo::NumMaterializations(deopt_instructions);
PrepareForDeferredMaterialization(num_materializations);
for (intptr_t from_index = 0, to_index = kDartFrameFixedSize;
from_index < num_materializations;
@@ -713,56 +713,6 @@ class DeoptCallerPcInstr : public DeoptInstr {
};
-// Deoptimization instruction that indicates the rest of this DeoptInfo is a
-// suffix of another one. The suffix contains the info number (0 based
-// index in the deopt table of the DeoptInfo to share) and the length of the
-// suffix.
-class DeoptSuffixInstr : public DeoptInstr {
- public:
- DeoptSuffixInstr(intptr_t info_number, intptr_t suffix_length)
- : info_number_(info_number), suffix_length_(suffix_length) {
- ASSERT(info_number >= 0);
- ASSERT(suffix_length >= 0);
- }
-
- explicit DeoptSuffixInstr(intptr_t source_index)
- : info_number_(InfoNumber::decode(source_index)),
- suffix_length_(SuffixLength::decode(source_index)) {
- }
-
- virtual intptr_t source_index() const {
- return InfoNumber::encode(info_number_) |
- SuffixLength::encode(suffix_length_);
- }
- virtual DeoptInstr::Kind kind() const { return kSuffix; }
-
- virtual const char* ArgumentsToCString() const {
- return Thread::Current()->zone()->PrintToString(
- "%" Pd ":%" Pd, info_number_, suffix_length_);
- }
-
- void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
- // The deoptimization info is uncompressed by translating away suffixes
- // before executing the instructions.
- UNREACHABLE();
- }
-
- private:
- // Static decoder functions in DeoptInstr have access to the bitfield
- // definitions.
- friend class DeoptInstr;
-
- static const intptr_t kFieldWidth = kBitsPerWord / 2;
- class InfoNumber : public BitField<intptr_t, 0, kFieldWidth> { };
- class SuffixLength : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
-
- const intptr_t info_number_;
- const intptr_t suffix_length_;
-
- DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr);
-};
-
-
// Write reference to a materialized object with the given index into the
// stack slot.
class DeoptMaterializedObjectRefInstr : public DeoptInstr {
@@ -823,13 +773,6 @@ class DeoptMaterializeObjectInstr : public DeoptInstr {
};
-intptr_t DeoptInstr::DecodeSuffix(intptr_t source_index,
- intptr_t* info_number) {
- *info_number = DeoptSuffixInstr::InfoNumber::decode(source_index);
- return DeoptSuffixInstr::SuffixLength::decode(source_index);
-}
-
-
uword DeoptInstr::GetRetAddress(DeoptInstr* instr,
const Array& object_table,
Code* code) {
@@ -888,8 +831,6 @@ DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) {
return new DeoptCallerPpInstr();
case kCallerPc:
return new DeoptCallerPcInstr();
- case kSuffix:
- return new DeoptSuffixInstr(source_index);
case kMaterializedObjectRef:
return new DeoptMaterializedObjectRefInstr(source_index);
case kMaterializeObject:
@@ -933,8 +874,6 @@ const char* DeoptInstr::KindToCString(Kind kind) {
return "callerpp";
case kCallerPc:
return "callerpc";
- case kSuffix:
- return "suffix";
case kMaterializedObjectRef:
return "ref";
case kMaterializeObject:
@@ -1216,19 +1155,22 @@ intptr_t DeoptInfoBuilder::FindMaterialization(
}
-RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) {
- // TODO(vegorov): enable compression of deoptimization info containing object
- // materialization instructions.
- const bool disable_compression =
- (instructions_[0]->kind() == DeoptInstr::kMaterializeObject);
+static uint8_t* ZoneReAlloc(uint8_t* ptr,
+ intptr_t old_size,
+ intptr_t new_size) {
+ return Isolate::Current()->current_zone()->Realloc<uint8_t>(
+ ptr, old_size, new_size);
+}
+
+RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) {
intptr_t length = instructions_.length();
// Count the number of instructions that are a shared suffix of some deopt
// info already written.
TrieNode* suffix = trie_root_;
intptr_t suffix_length = 0;
- if (FLAG_compress_deopt_info && !disable_compression) {
+ if (FLAG_compress_deopt_info) {
for (intptr_t i = length - 1; i >= 0; --i) {
TrieNode* node = suffix->FindChild(*instructions_[i]);
if (node == NULL) break;
@@ -1237,33 +1179,51 @@ RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) {
}
}
+
// Allocate space for the translation. If the shared suffix is longer
// than one instruction, we replace it with a single suffix instruction.
- if (suffix_length > 1) length -= (suffix_length - 1);
- const DeoptInfo& deopt_info =
- DeoptInfo::Handle(zone(), DeoptInfo::New(length));
+ const bool use_suffix = suffix_length > 1;
+ if (use_suffix) {
+ length -= (suffix_length - 1);
+ }
+
+ uint8_t* buffer;
+ typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer;
+ WriteStream stream(&buffer, ZoneReAlloc, 2 * length * kWordSize);
+
+ Writer::Write(&stream, FrameSize());
+
+ if (use_suffix) {
+ Writer::Write(&stream, suffix_length);
+ Writer::Write(&stream, suffix->info_number());
+ } else {
+ Writer::Write(&stream, 0);
+ }
// Write the unshared instructions and build their sub-tree.
- TrieNode* node = NULL;
- intptr_t write_count = (suffix_length > 1) ? length - 1 : length;
- for (intptr_t i = 0; i < write_count; ++i) {
+ TrieNode* node = use_suffix ? suffix : trie_root_;
+ const intptr_t write_count = use_suffix ? length - 1 : length;
+ for (intptr_t i = write_count - 1; i >= 0; --i) {
DeoptInstr* instr = instructions_[i];
- deopt_info.SetAt(i, instr->kind(), instr->source_index());
- TrieNode* child = node;
- node = new(zone()) TrieNode(instr, current_info_number_);
+ Writer::Write(&stream, instr->kind());
+ Writer::Write(&stream, instr->source_index());
+
+ TrieNode* child = new(zone()) TrieNode(instr, current_info_number_);
node->AddChild(child);
+ node = child;
}
- if (suffix_length > 1) {
- suffix->AddChild(node);
- DeoptInstr* instr =
- new(zone()) DeoptSuffixInstr(suffix->info_number(), suffix_length);
- deopt_info.SetAt(length - 1, instr->kind(), instr->source_index());
- } else {
- trie_root_->AddChild(node);
+ const TypedData& deopt_info = TypedData::Handle(zone(), TypedData::New(
+ kTypedDataUint8ArrayCid, stream.bytes_written(), Heap::kOld));
+ {
+ NoSafepointScope no_safepoint;
+ memmove(deopt_info.DataAddr(0),
+ stream.buffer(),
+ stream.bytes_written());
}
- ASSERT(deopt_info.VerifyDecompression(instructions_, deopt_table));
+ ASSERT(DeoptInfo::VerifyDecompression(
+ instructions_, deopt_table, deopt_info));
instructions_.Clear();
materializations_.Clear();
frame_start_ = -1;
@@ -1280,7 +1240,7 @@ intptr_t DeoptTable::SizeFor(intptr_t length) {
void DeoptTable::SetEntry(const Array& table,
intptr_t index,
const Smi& offset,
- const DeoptInfo& info,
+ const TypedData& info,
const Smi& reason) {
ASSERT((table.Length() % kEntrySize) == 0);
intptr_t i = index * kEntrySize;
@@ -1299,7 +1259,7 @@ intptr_t DeoptTable::GetLength(const Array& table) {
void DeoptTable::GetEntry(const Array& table,
intptr_t index,
Smi* offset,
- DeoptInfo* info,
+ TypedData* info,
Smi* reason) {
intptr_t i = index * kEntrySize;
*offset ^= table.At(i);
« no previous file with comments | « runtime/vm/deopt_instructions.h ('k') | runtime/vm/flow_graph_compiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698