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

Unified Diff: runtime/vm/code_descriptors.cc

Issue 2670843006: Encode inlining information in CodeSourceMap and remove inlining interval arrays. (Closed)
Patch Set: . Created 3 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
« no previous file with comments | « runtime/vm/code_descriptors.h ('k') | runtime/vm/code_descriptors_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/code_descriptors.cc
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index 1e6ff220ba094b03d6dd56e37d5e1c0311ffd6b6..0631bfee3f588446607221bb43bd48133a093a26 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -4,6 +4,8 @@
#include "vm/code_descriptors.h"
+#include "vm/log.h"
+
namespace dart {
void DescriptorList::AddDescriptor(RawPcDescriptors::Kind kind,
@@ -41,25 +43,6 @@ RawPcDescriptors* DescriptorList::FinalizePcDescriptors(uword entry_point) {
}
-void CodeSourceMapBuilder::AddEntry(intptr_t pc_offset,
- TokenPosition token_pos) {
- // Require pc offset to monotonically increase.
- ASSERT((prev_pc_offset < pc_offset) ||
- ((prev_pc_offset == 0) && (pc_offset == 0)));
- CodeSourceMap::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset);
- CodeSourceMap::EncodeInteger(&encoded_data_,
- token_pos.value() - prev_token_pos);
-
- prev_pc_offset = pc_offset;
- prev_token_pos = token_pos.value();
-}
-
-
-RawCodeSourceMap* CodeSourceMapBuilder::Finalize() {
- return CodeSourceMap::New(&encoded_data_);
-}
-
-
void StackMapTableBuilder::AddEntry(intptr_t pc_offset,
BitmapBuilder* bitmap,
intptr_t register_bit_count) {
@@ -132,4 +115,343 @@ RawExceptionHandlers* ExceptionHandlerList::FinalizeExceptionHandlers(
}
+static uint8_t* zone_allocator(uint8_t* ptr,
+ intptr_t old_size,
+ intptr_t new_size) {
+ Zone* zone = Thread::Current()->zone();
+ return zone->Realloc<uint8_t>(ptr, old_size, new_size);
+}
+
+
+const TokenPosition CodeSourceMapBuilder::kInitialPosition =
+ TokenPosition::kDartCodePrologue;
+
+
+CodeSourceMapBuilder::CodeSourceMapBuilder(
+ const GrowableArray<intptr_t>& caller_inline_id,
+ const GrowableArray<TokenPosition>& inline_id_to_token_pos,
+ const GrowableArray<const Function*>& inline_id_to_function)
+ : pc_offset_(0),
+ advance_pc_peephole_(0),
+ inline_id_stack_(),
+ token_pos_stack_(),
+ caller_inline_id_(caller_inline_id),
+ inline_id_to_token_pos_(inline_id_to_token_pos),
+ inline_id_to_function_(inline_id_to_function),
+ buffer_(NULL),
+ stream_(&buffer_, zone_allocator, 64) {
+ inline_id_stack_.Add(0);
+ token_pos_stack_.Add(TokenPosition::kDartCodePrologue);
+}
+
+
+void CodeSourceMapBuilder::StartInliningInterval(int32_t pc_offset,
+ intptr_t inline_id) {
+ if (inline_id_stack_.Last() == inline_id) {
+ // No change in function stack.
+ return;
+ }
+ if (inline_id == -1) {
+ // Basic blocking missing an inline_id.
+ return;
+ }
+
+ // Find a minimal set of pops and pushes to bring us to the new function
+ // stack.
+
+ // Pop to a common ancestor.
+ intptr_t common_parent = inline_id;
+ while (!IsOnStack(common_parent)) {
+ common_parent = caller_inline_id_[common_parent];
+ }
+ while (inline_id_stack_.Last() != common_parent) {
+ EmitPop();
+ inline_id_stack_.RemoveLast();
+ token_pos_stack_.RemoveLast();
+ }
+
+ // Push to the new top-of-stack function.
+ GrowableArray<intptr_t> to_push;
+ intptr_t id = inline_id;
+ while (id != common_parent) {
+ to_push.Add(id);
+ id = caller_inline_id_[id];
+ }
+ for (intptr_t i = to_push.length() - 1; i >= 0; i--) {
+ intptr_t push_id = to_push[i];
+ TokenPosition call_token;
+ if (push_id != 0) {
+ // TODO(rmacnak): Should make this array line up with the others.
+ call_token = inline_id_to_token_pos_[push_id - 1];
+ }
+
+ // Report caller as at the position of the call.
+ if (call_token != token_pos_stack_.Last()) {
+ EmitPosition(call_token);
+ token_pos_stack_[token_pos_stack_.length() - 1] = call_token;
+ }
+
+ // Push the callee.
+ EmitPush(push_id);
+ inline_id_stack_.Add(push_id);
+ token_pos_stack_.Add(TokenPosition::kDartCodePrologue);
+ }
+}
+
+
+void CodeSourceMapBuilder::BeginCodeSourceRange(int32_t pc_offset) {}
+
+
+void CodeSourceMapBuilder::EndCodeSourceRange(int32_t pc_offset,
+ TokenPosition pos) {
+ if (pc_offset == pc_offset_) {
+ return; // Empty intermediate instruction.
+ }
+ if (pos != token_pos_stack_.Last()) {
+ EmitPosition(pos);
+ token_pos_stack_[token_pos_stack_.length() - 1] = pos;
+ }
+ EmitAdvancePC(pc_offset - pc_offset_);
+ pc_offset_ = pc_offset;
+}
+
+
+RawArray* CodeSourceMapBuilder::InliningIdToFunction() {
+ if (inline_id_to_function_.length() <= 1) {
+ // Not optimizing, or optimizing and nothing inlined.
+ return Object::empty_array().raw();
+ }
+ const Array& res =
+ Array::Handle(Array::New(inline_id_to_function_.length(), Heap::kOld));
+ for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) {
+ res.SetAt(i, *inline_id_to_function_[i]);
+ }
+ return res.raw();
+}
+
+
+RawCodeSourceMap* CodeSourceMapBuilder::Finalize() {
+ FlushPeephole();
+ intptr_t length = stream_.bytes_written();
+ const CodeSourceMap& map = CodeSourceMap::Handle(CodeSourceMap::New(length));
+ NoSafepointScope no_safepoint;
+ memmove(map.Data(), buffer_, length);
+ return map.raw();
+}
+
+
+void CodeSourceMapReader::GetInlinedFunctionsAt(
+ int32_t pc_offset,
+ GrowableArray<const Function*>* function_stack,
+ GrowableArray<TokenPosition>* token_positions) {
+ function_stack->Clear();
+ token_positions->Clear();
+
+ NoSafepointScope no_safepoint;
+ ReadStream stream(map_.Data(), map_.Length());
+
+ int32_t current_pc_offset = 0;
+ function_stack->Add(&root_);
+ token_positions->Add(CodeSourceMapBuilder::kInitialPosition);
+
+ while (stream.PendingBytes() > 0) {
+ uint8_t opcode = stream.Read<uint8_t>();
+ switch (opcode) {
+ case CodeSourceMapBuilder::kChangePosition: {
+ int32_t position = stream.Read<int32_t>();
+ (*token_positions)[token_positions->length() - 1] =
+ TokenPosition(position);
+ break;
+ }
+ case CodeSourceMapBuilder::kAdvancePC: {
+ int32_t delta = stream.Read<int32_t>();
+ current_pc_offset += delta;
+ if (current_pc_offset > pc_offset) {
+ return;
+ }
+ break;
+ }
+ case CodeSourceMapBuilder::kPushFunction: {
+ int32_t func = stream.Read<int32_t>();
+ function_stack->Add(
+ &Function::Handle(Function::RawCast(functions_.At(func))));
+ token_positions->Add(CodeSourceMapBuilder::kInitialPosition);
+ break;
+ }
+ case CodeSourceMapBuilder::kPopFunction: {
+ // We never pop the root function.
+ ASSERT(function_stack->length() > 1);
+ ASSERT(token_positions->length() > 1);
+ function_stack->RemoveLast();
+ token_positions->RemoveLast();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+}
+
+
+#ifndef PRODUCT
+void CodeSourceMapReader::PrintJSONInlineIntervals(JSONObject* jsobj) {
+ {
+ JSONArray inlined_functions(jsobj, "_inlinedFunctions");
+ Function& function = Function::Handle();
+ for (intptr_t i = 0; i < functions_.Length(); i++) {
+ function ^= functions_.At(i);
+ ASSERT(!function.IsNull());
+ inlined_functions.AddValue(function);
+ }
+ }
+
+ GrowableArray<intptr_t> function_stack;
+ JSONArray inline_intervals(jsobj, "_inlinedIntervals");
+ NoSafepointScope no_safepoint;
+ ReadStream stream(map_.Data(), map_.Length());
+
+ int32_t current_pc_offset = 0;
+ function_stack.Add(0);
+
+ while (stream.PendingBytes() > 0) {
+ uint8_t opcode = stream.Read<uint8_t>();
+ switch (opcode) {
+ case CodeSourceMapBuilder::kChangePosition: {
+ stream.Read<int32_t>();
+ break;
+ }
+ case CodeSourceMapBuilder::kAdvancePC: {
+ int32_t delta = stream.Read<int32_t>();
+ // Format: [start, end, inline functions...]
+ JSONArray inline_interval(&inline_intervals);
+ inline_interval.AddValue(static_cast<intptr_t>(current_pc_offset));
+ inline_interval.AddValue(
+ static_cast<intptr_t>(current_pc_offset + delta - 1));
+ for (intptr_t i = 0; i < function_stack.length(); i++) {
+ inline_interval.AddValue(function_stack[i]);
+ }
+ current_pc_offset += delta;
+ break;
+ }
+ case CodeSourceMapBuilder::kPushFunction: {
+ int32_t func = stream.Read<int32_t>();
+ function_stack.Add(func);
+ break;
+ }
+ case CodeSourceMapBuilder::kPopFunction: {
+ // We never pop the root function.
+ ASSERT(function_stack.length() > 1);
+ function_stack.RemoveLast();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+}
+#endif // !PRODUCT
+
+
+void CodeSourceMapReader::DumpInlineIntervals(uword start) {
+ GrowableArray<const Function*> function_stack;
+ LogBlock lb;
+ NoSafepointScope no_safepoint;
+ ReadStream stream(map_.Data(), map_.Length());
+
+ int32_t current_pc_offset = 0;
+ function_stack.Add(&root_);
+
+ THR_Print("Inline intervals {\n");
+ while (stream.PendingBytes() > 0) {
+ uint8_t opcode = stream.Read<uint8_t>();
+ switch (opcode) {
+ case CodeSourceMapBuilder::kChangePosition: {
+ stream.Read<int32_t>();
+ break;
+ }
+ case CodeSourceMapBuilder::kAdvancePC: {
+ int32_t delta = stream.Read<int32_t>();
+ THR_Print("%" Px "-%" Px ": ", start + current_pc_offset,
+ start + current_pc_offset + delta - 1);
+ for (intptr_t i = 0; i < function_stack.length(); i++) {
+ THR_Print("%s ", function_stack[i]->ToCString());
+ }
+ THR_Print("\n");
+ current_pc_offset += delta;
+ break;
+ }
+ case CodeSourceMapBuilder::kPushFunction: {
+ int32_t func = stream.Read<int32_t>();
+ function_stack.Add(
+ &Function::Handle(Function::RawCast(functions_.At(func))));
+ break;
+ }
+ case CodeSourceMapBuilder::kPopFunction: {
+ // We never pop the root function.
+ ASSERT(function_stack.length() > 1);
+ function_stack.RemoveLast();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+ THR_Print("}\n");
+}
+
+
+void CodeSourceMapReader::DumpSourcePositions(uword start) {
+ GrowableArray<const Function*> function_stack;
+ GrowableArray<TokenPosition> token_positions;
+ LogBlock lb;
+ NoSafepointScope no_safepoint;
+ ReadStream stream(map_.Data(), map_.Length());
+
+ int32_t current_pc_offset = 0;
+ function_stack.Add(&root_);
+ token_positions.Add(CodeSourceMapBuilder::kInitialPosition);
+
+ THR_Print("Source positions {\n");
+ while (stream.PendingBytes() > 0) {
+ uint8_t opcode = stream.Read<uint8_t>();
+ switch (opcode) {
+ case CodeSourceMapBuilder::kChangePosition: {
+ int32_t position = stream.Read<int32_t>();
+ token_positions[token_positions.length() - 1] = TokenPosition(position);
+ break;
+ }
+ case CodeSourceMapBuilder::kAdvancePC: {
+ int32_t delta = stream.Read<int32_t>();
+ THR_Print("%" Px "-%" Px ": ", start + current_pc_offset,
+ start + current_pc_offset + delta - 1);
+ for (intptr_t i = 0; i < function_stack.length(); i++) {
+ THR_Print("%s@%" Pd " ", function_stack[i]->ToCString(),
+ token_positions[i].value());
+ }
+ THR_Print("\n");
+ current_pc_offset += delta;
+ break;
+ }
+ case CodeSourceMapBuilder::kPushFunction: {
+ int32_t func = stream.Read<int32_t>();
+ function_stack.Add(
+ &Function::Handle(Function::RawCast(functions_.At(func))));
+ token_positions.Add(CodeSourceMapBuilder::kInitialPosition);
+ break;
+ }
+ case CodeSourceMapBuilder::kPopFunction: {
+ // We never pop the root function.
+ ASSERT(function_stack.length() > 1);
+ ASSERT(token_positions.length() > 1);
+ function_stack.RemoveLast();
+ token_positions.RemoveLast();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+ THR_Print("}\n");
+}
+
} // namespace dart
« no previous file with comments | « runtime/vm/code_descriptors.h ('k') | runtime/vm/code_descriptors_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698