Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index b2b922b9888876b4bbc48aaa3217edad5b2bed53..8df9f9333e007d2bbbb11a80e977f1c75be8093a 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -12096,117 +12096,11 @@ void PcDescriptors::Verify(const Function& function) const { |
} |
-TokenPosition CodeSourceMap::TokenPositionForPCOffset(uword pc_offset) const { |
- Iterator iterator(*this); |
- |
- TokenPosition result = TokenPosition::kNoSource; |
- |
- while (iterator.MoveNext()) { |
- if (iterator.PcOffset() > pc_offset) { |
- break; |
- } |
- result = iterator.TokenPos(); |
- } |
- |
- return result; |
-} |
- |
- |
-RawFunction* CodeSourceMap::FunctionForPCOffset(const Code& code, |
- const Function& function, |
- uword pc_offset) const { |
- GrowableArray<Function*> inlined_functions; |
- code.GetInlinedFunctionsAt(pc_offset, &inlined_functions); |
- if (inlined_functions.length() > 0) { |
- Function* inlined_function = inlined_functions[0]; |
- return inlined_function->raw(); |
- } else { |
- return function.raw(); |
- } |
-} |
- |
- |
-RawScript* CodeSourceMap::ScriptForPCOffset(const Code& code, |
- const Function& function, |
- uword pc_offset) const { |
- const Function& func = |
- Function::Handle(FunctionForPCOffset(code, function, pc_offset)); |
- return func.script(); |
-} |
- |
- |
-void CodeSourceMap::Dump(const CodeSourceMap& code_source_map, |
- const Code& code, |
- const Function& function) { |
- const char* code_name = code.QualifiedName(); |
- THR_Print("Dumping Code Source Map for %s\n", code_name); |
- if (code_source_map.Length() == 0) { |
- THR_Print("<empty>\n"); |
- return; |
- } |
- |
- const int addr_width = kBitsPerWord / 4; |
- |
- Iterator iterator(code_source_map); |
- Function& current_function = Function::Handle(); |
- Script& current_script = Script::Handle(); |
- TokenPosition tp; |
- while (iterator.MoveNext()) { |
- const uword pc_offset = iterator.PcOffset(); |
- tp = code_source_map.TokenPositionForPCOffset(pc_offset); |
- current_function ^= |
- code_source_map.FunctionForPCOffset(code, function, pc_offset); |
- current_script ^= |
- code_source_map.ScriptForPCOffset(code, function, pc_offset); |
- if (current_function.IsNull() || current_script.IsNull()) { |
- THR_Print("%#-*" Px "\t%s\t%s\n", addr_width, pc_offset, tp.ToCString(), |
- code_name); |
- continue; |
- } |
- const String& uri = String::Handle(current_script.url()); |
- ASSERT(!uri.IsNull()); |
- THR_Print("%#-*" Px "\t%s\t%s\t%s\n", addr_width, pc_offset, tp.ToCString(), |
- current_function.ToQualifiedCString(), uri.ToCString()); |
- } |
-} |
- |
- |
-intptr_t CodeSourceMap::Length() const { |
- return raw_ptr()->length_; |
-} |
- |
- |
void CodeSourceMap::SetLength(intptr_t value) const { |
StoreNonPointer(&raw_ptr()->length_, value); |
} |
-void CodeSourceMap::CopyData(GrowableArray<uint8_t>* delta_encoded_data) { |
- NoSafepointScope no_safepoint; |
- uint8_t* data = UnsafeMutableNonPointer(&raw_ptr()->data()[0]); |
- for (intptr_t i = 0; i < delta_encoded_data->length(); ++i) { |
- data[i] = (*delta_encoded_data)[i]; |
- } |
-} |
- |
- |
-RawCodeSourceMap* CodeSourceMap::New(GrowableArray<uint8_t>* data) { |
- ASSERT(Object::code_source_map_class() != Class::null()); |
- Thread* thread = Thread::Current(); |
- CodeSourceMap& result = CodeSourceMap::Handle(thread->zone()); |
- { |
- uword size = CodeSourceMap::InstanceSize(data->length()); |
- RawObject* raw = |
- Object::Allocate(CodeSourceMap::kClassId, size, Heap::kOld); |
- NoSafepointScope no_safepoint; |
- result ^= raw; |
- result.SetLength(data->length()); |
- result.CopyData(data); |
- } |
- return result.raw(); |
-} |
- |
- |
RawCodeSourceMap* CodeSourceMap::New(intptr_t length) { |
ASSERT(Object::code_source_map_class() != Class::null()); |
Thread* thread = Thread::Current(); |
@@ -12224,49 +12118,7 @@ RawCodeSourceMap* CodeSourceMap::New(intptr_t length) { |
const char* CodeSourceMap::ToCString() const { |
-// "*" in a printf format specifier tells it to read the field width from |
-// the printf argument list. |
-#define FORMAT "%#-*" Px "\t%s\n" |
- if (Length() == 0) { |
- return "empty CodeSourceMap\n"; |
- } |
- // 4 bits per hex digit. |
- const int addr_width = kBitsPerWord / 4; |
- // First compute the buffer size required. |
- intptr_t len = 1; // Trailing '\0'. |
- { |
- Iterator iter(*this); |
- while (iter.MoveNext()) { |
- len += OS::SNPrint(NULL, 0, FORMAT, addr_width, iter.PcOffset(), |
- iter.TokenPos().ToCString()); |
- } |
- } |
- // Allocate the buffer. |
- char* buffer = Thread::Current()->zone()->Alloc<char>(len); |
- // Layout the fields in the buffer. |
- intptr_t index = 0; |
- Iterator iter(*this); |
- while (iter.MoveNext()) { |
- index += OS::SNPrint((buffer + index), (len - index), FORMAT, addr_width, |
- iter.PcOffset(), iter.TokenPos().ToCString()); |
- } |
- return buffer; |
-#undef FORMAT |
-} |
- |
- |
-// Encode integer in SLEB128 format. |
-void CodeSourceMap::EncodeInteger(GrowableArray<uint8_t>* data, |
- intptr_t value) { |
- return EncodeSLEB128(data, value); |
-} |
- |
- |
-// Decode SLEB128 encoded integer. Update byte_index to the next integer. |
-intptr_t CodeSourceMap::DecodeInteger(intptr_t* byte_index) const { |
- NoSafepointScope no_safepoint; |
- const uint8_t* data = raw_ptr()->data(); |
- return DecodeSLEB128(data, Length(), byte_index); |
+ return "CodeSourceMap"; |
} |
@@ -14047,15 +13899,6 @@ bool Code::HasBreakpoint() const { |
} |
-TokenPosition Code::GetTokenPositionAt(intptr_t offset) const { |
- const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); |
- if (map.IsNull()) { |
- return TokenPosition::kNoSource; |
- } |
- return map.TokenPositionForPCOffset(offset); |
-} |
- |
- |
RawTypedData* Code::GetDeoptInfoAtPc(uword pc, |
ICData::DeoptReasonId* deopt_reason, |
uint32_t* deopt_flags) const { |
@@ -14243,126 +14086,21 @@ intptr_t Code::GetPrologueOffset() const { |
} |
-RawArray* Code::GetInlinedIntervals() const { |
-#if defined(DART_PRECOMPILED_RUNTIME) |
- return Array::null(); |
-#else |
- const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
- if (metadata.IsNull()) { |
- return metadata.raw(); |
- } |
- return reinterpret_cast<RawArray*>( |
- metadata.At(RawCode::kInlinedIntervalsIndex)); |
-#endif |
-} |
- |
- |
-void Code::SetInlinedIntervals(const Array& value) const { |
-#if defined(DART_PRECOMPILED_RUNTIME) |
- UNREACHABLE(); |
-#else |
- if (raw_ptr()->inlined_metadata_ == Array::null()) { |
- StorePointer(&raw_ptr()->inlined_metadata_, |
- Array::New(RawCode::kInlinedMetadataSize, Heap::kOld)); |
- } |
- const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
- ASSERT(!metadata.IsNull()); |
- ASSERT(metadata.IsOld()); |
- ASSERT(value.IsOld()); |
- metadata.SetAt(RawCode::kInlinedIntervalsIndex, value); |
-#endif |
-} |
- |
- |
-RawArray* Code::GetInlinedIdToFunction() const { |
-#if defined(DART_PRECOMPILED_RUNTIME) |
- return Array::null(); |
-#else |
- const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
- if (metadata.IsNull()) { |
- return metadata.raw(); |
- } |
- return reinterpret_cast<RawArray*>( |
- metadata.At(RawCode::kInlinedIdToFunctionIndex)); |
-#endif |
-} |
- |
- |
-void Code::SetInlinedIdToFunction(const Array& value) const { |
-#if defined(DART_PRECOMPILED_RUNTIME) |
- UNREACHABLE(); |
-#else |
- if (raw_ptr()->inlined_metadata_ == Array::null()) { |
- StorePointer(&raw_ptr()->inlined_metadata_, |
- Array::New(RawCode::kInlinedMetadataSize, Heap::kOld)); |
- } |
- const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
- ASSERT(!metadata.IsNull()); |
- ASSERT(metadata.IsOld()); |
- ASSERT(value.IsOld()); |
- metadata.SetAt(RawCode::kInlinedIdToFunctionIndex, value); |
-#endif |
-} |
- |
- |
-RawArray* Code::GetInlinedIdToTokenPos() const { |
-#if defined(DART_PRECOMPILED_RUNTIME) |
- return Array::null(); |
-#else |
- const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
- if (metadata.IsNull()) { |
- return metadata.raw(); |
- } |
- return reinterpret_cast<RawArray*>( |
- metadata.At(RawCode::kInlinedIdToTokenPosIndex)); |
-#endif |
-} |
- |
- |
-void Code::SetInlinedIdToTokenPos(const Array& value) const { |
-#if defined(DART_PRECOMPILED_RUNTIME) |
- UNREACHABLE(); |
-#else |
- if (raw_ptr()->inlined_metadata_ == Array::null()) { |
- StorePointer(&raw_ptr()->inlined_metadata_, |
- Array::New(RawCode::kInlinedMetadataSize, Heap::kOld)); |
- } |
- const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
- ASSERT(!metadata.IsNull()); |
- ASSERT(metadata.IsOld()); |
- ASSERT(value.IsOld()); |
- metadata.SetAt(RawCode::kInlinedIdToTokenPosIndex, value); |
-#endif |
-} |
- |
- |
-RawArray* Code::GetInlinedCallerIdMap() const { |
+RawArray* Code::inlined_id_to_function() const { |
#if defined(DART_PRECOMPILED_RUNTIME) |
return Array::null(); |
#else |
- const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
- if (metadata.IsNull()) { |
- return metadata.raw(); |
- } |
- return reinterpret_cast<RawArray*>( |
- metadata.At(RawCode::kInlinedCallerIdMapIndex)); |
+ return raw_ptr()->inlined_id_to_function_; |
#endif |
} |
-void Code::SetInlinedCallerIdMap(const Array& value) const { |
+void Code::set_inlined_id_to_function(const Array& value) const { |
#if defined(DART_PRECOMPILED_RUNTIME) |
UNREACHABLE(); |
#else |
- if (raw_ptr()->inlined_metadata_ == Array::null()) { |
- StorePointer(&raw_ptr()->inlined_metadata_, |
- Array::New(RawCode::kInlinedMetadataSize, Heap::kOld)); |
- } |
- const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
- ASSERT(!metadata.IsNull()); |
- ASSERT(metadata.IsOld()); |
ASSERT(value.IsOld()); |
- metadata.SetAt(RawCode::kInlinedCallerIdMapIndex, value); |
+ StorePointer(&raw_ptr()->inlined_id_to_function_, value.raw()); |
#endif |
} |
@@ -14722,126 +14460,59 @@ RawStackMap* Code::GetStackMap(uint32_t pc_offset, |
} |
-intptr_t Code::GetCallerId(intptr_t inlined_id) const { |
- if (inlined_id < 0) { |
- return -1; |
- } |
- const Array& map = Array::Handle(GetInlinedCallerIdMap()); |
- if (map.IsNull() || (map.Length() == 0)) { |
- return -1; |
+void Code::GetInlinedFunctionsAt( |
+ intptr_t pc_offset, |
+ GrowableArray<const Function*>* functions, |
+ GrowableArray<TokenPosition>* token_positions) const { |
+ const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); |
+ if (map.IsNull()) { |
+ // Stub code. |
+ return; |
} |
- Smi& smi = Smi::Handle(); |
- smi ^= map.At(inlined_id); |
- return smi.Value(); |
+ const Array& id_map = Array::Handle(inlined_id_to_function()); |
+ const Function& root = Function::Handle(function()); |
+ CodeSourceMapReader reader(map, id_map, root); |
+ reader.GetInlinedFunctionsAt(pc_offset, functions, token_positions); |
} |
-void Code::GetInlinedFunctionsAt( |
- intptr_t offset, |
- GrowableArray<Function*>* fs, |
- GrowableArray<TokenPosition>* token_positions) const { |
- fs->Clear(); |
- if (token_positions != NULL) { |
- token_positions->Clear(); |
+#ifndef PRODUCT |
+void Code::PrintJSONInlineIntervals(JSONObject* jsobj) const { |
+ if (!is_optimized()) { |
+ return; // No inlining. |
} |
- const Array& intervals = Array::Handle(GetInlinedIntervals()); |
- if (intervals.IsNull() || (intervals.Length() == 0)) { |
- // E.g., for code stubs. |
+ const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); |
+ const Array& id_map = Array::Handle(inlined_id_to_function()); |
+ const Function& root = Function::Handle(function()); |
+ CodeSourceMapReader reader(map, id_map, root); |
+ reader.PrintJSONInlineIntervals(jsobj); |
+} |
+#endif |
+ |
+ |
+void Code::DumpInlineIntervals() const { |
+ const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); |
+ if (map.IsNull()) { |
+ // Stub code. |
return; |
} |
- // First find the right interval. TODO(srdjan): use binary search since |
- // intervals are sorted. |
- Smi& start = Smi::Handle(); |
- Smi& end = Smi::Handle(); |
- intptr_t found_interval_ix = intervals.Length() - Code::kInlIntNumEntries; |
- for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries; |
- i += Code::kInlIntNumEntries) { |
- start ^= intervals.At(i + Code::kInlIntStart); |
- if (!start.IsNull()) { |
- end ^= intervals.At(i + Code::kInlIntNumEntries + Code::kInlIntStart); |
- if ((start.Value() <= offset) && (offset < end.Value())) { |
- found_interval_ix = i; |
- break; |
- } |
- } |
- } |
+ const Array& id_map = Array::Handle(inlined_id_to_function()); |
+ const Function& root = Function::Handle(function()); |
+ CodeSourceMapReader reader(map, id_map, root); |
+ reader.DumpInlineIntervals(PayloadStart()); |
+} |
- // Find all functions. |
- const Array& id_map = Array::Handle(GetInlinedIdToFunction()); |
- const Array& token_pos_map = Array::Handle(GetInlinedIdToTokenPos()); |
- Smi& temp_smi = Smi::Handle(); |
- temp_smi ^= intervals.At(found_interval_ix + Code::kInlIntInliningId); |
- intptr_t inlining_id = temp_smi.Value(); |
- ASSERT(inlining_id >= 0); |
- intptr_t caller_id = GetCallerId(inlining_id); |
- while (inlining_id >= 0) { |
- Function& function = Function::ZoneHandle(); |
- function ^= id_map.At(inlining_id); |
- fs->Add(&function); |
- if ((token_positions != NULL) && (inlining_id < token_pos_map.Length())) { |
- temp_smi ^= token_pos_map.At(inlining_id); |
- token_positions->Add(TokenPosition(temp_smi.Value())); |
- } |
- inlining_id = caller_id; |
- caller_id = GetCallerId(inlining_id); |
- } |
-} |
- |
- |
-void Code::DumpInlinedIntervals() const { |
- LogBlock lb; |
- THR_Print("Inlined intervals:\n"); |
- const Array& intervals = Array::Handle(GetInlinedIntervals()); |
- if (intervals.IsNull() || (intervals.Length() == 0)) return; |
- Smi& start = Smi::Handle(); |
- Smi& inlining_id = Smi::Handle(); |
- GrowableArray<Function*> inlined_functions; |
- const Function& inliner = Function::Handle(function()); |
- for (intptr_t i = 0; i < intervals.Length(); i += Code::kInlIntNumEntries) { |
- start ^= intervals.At(i + Code::kInlIntStart); |
- ASSERT(!start.IsNull()); |
- if (start.IsNull()) continue; |
- inlining_id ^= intervals.At(i + Code::kInlIntInliningId); |
- THR_Print(" %" Px " iid: %" Pd " ; ", start.Value(), inlining_id.Value()); |
- inlined_functions.Clear(); |
- |
- THR_Print("inlined: "); |
- GetInlinedFunctionsAt(start.Value(), &inlined_functions); |
- |
- for (intptr_t j = 0; j < inlined_functions.length(); j++) { |
- const char* name = inlined_functions[j]->ToQualifiedCString(); |
- THR_Print(" %s <-", name); |
- } |
- if (inlined_functions[inlined_functions.length() - 1]->raw() != |
- inliner.raw()) { |
- THR_Print(" (ERROR, missing inliner)\n"); |
- } else { |
- THR_Print("\n"); |
- } |
- } |
- THR_Print("Inlined ids:\n"); |
- const Array& id_map = Array::Handle(GetInlinedIdToFunction()); |
- Function& function = Function::Handle(); |
- for (intptr_t i = 0; i < id_map.Length(); i++) { |
- function ^= id_map.At(i); |
- if (!function.IsNull()) { |
- THR_Print(" %" Pd ": %s\n", i, function.ToQualifiedCString()); |
- } |
- } |
- THR_Print("Inlined token pos:\n"); |
- const Array& token_pos_map = Array::Handle(GetInlinedIdToTokenPos()); |
- Smi& smi = Smi::Handle(); |
- for (intptr_t i = 0; i < token_pos_map.Length(); i++) { |
- smi ^= token_pos_map.At(i); |
- TokenPosition tp = TokenPosition(smi.Value()); |
- THR_Print(" %" Pd ": %s\n", i, tp.ToCString()); |
- } |
- THR_Print("Caller Inlining Ids:\n"); |
- const Array& caller_map = Array::Handle(GetInlinedCallerIdMap()); |
- for (intptr_t i = 0; i < caller_map.Length(); i++) { |
- smi ^= caller_map.At(i); |
- THR_Print(" iid: %" Pd " caller iid: %" Pd "\n", i, smi.Value()); |
+ |
+void Code::DumpSourcePositions() const { |
+ const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); |
+ if (map.IsNull()) { |
+ // Stub code. |
+ return; |
} |
+ const Array& id_map = Array::Handle(inlined_id_to_function()); |
+ const Function& root = Function::Handle(function()); |
+ CodeSourceMapReader reader(map, id_map, root); |
+ reader.DumpSourcePositions(PayloadStart()); |
} |