| // Copyright 2016 the V8 project authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/source-position.h" | |
| #include "src/objects-inl.h" | |
| #include "src/optimized-compilation-info.h" | |
| namespace v8 { | |
| namespace internal { | |
| std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos) { | |
| out << "<"; | |
| if (!pos.script.is_null() && pos.script->name()->IsString()) { | |
| out << String::cast(pos.script->name())->ToCString(DISALLOW_NULLS).get(); | |
| } else { | |
| out << "unknown"; | |
| } | |
| out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">"; | |
| return out; | |
| } | |
| std::ostream& operator<<(std::ostream& out, | |
| const std::vector<SourcePositionInfo>& stack) { | |
| bool first = true; | |
| for (const SourcePositionInfo& pos : stack) { | |
| if (!first) out << " inlined at "; | |
| out << pos; | |
| first = false; | |
| } | |
| return out; | |
| } | |
| std::ostream& operator<<(std::ostream& out, const SourcePosition& pos) { | |
| if (pos.isInlined()) { | |
| out << "<inlined(" << pos.InliningId() << "):"; | |
| } else { | |
| out << "<not inlined:"; | |
| } | |
| out << pos.ScriptOffset() << ">"; | |
| return out; | |
| } | |
| std::vector<SourcePositionInfo> SourcePosition::InliningStack( | |
| OptimizedCompilationInfo* cinfo) const { | |
| SourcePosition pos = *this; | |
| std::vector<SourcePositionInfo> stack; | |
| while (pos.isInlined()) { | |
| const auto& inl = cinfo->inlined_functions()[pos.InliningId()]; | |
| stack.push_back(SourcePositionInfo(pos, inl.shared_info)); | |
| pos = inl.position.position; | |
| } | |
| stack.push_back(SourcePositionInfo(pos, cinfo->shared_info())); | |
| return stack; | |
| } | |
| std::vector<SourcePositionInfo> SourcePosition::InliningStack( | |
| Handle<Code> code) const { | |
| Isolate* isolate = code->GetIsolate(); | |
| Handle<DeoptimizationData> deopt_data( | |
| DeoptimizationData::cast(code->deoptimization_data()), isolate); | |
| SourcePosition pos = *this; | |
| std::vector<SourcePositionInfo> stack; | |
| while (pos.isInlined()) { | |
| InliningPosition inl = | |
| deopt_data->InliningPositions()->get(pos.InliningId()); | |
| Handle<SharedFunctionInfo> function( | |
| deopt_data->GetInlinedFunction(inl.inlined_function_id), isolate); | |
| stack.push_back(SourcePositionInfo(pos, function)); | |
| pos = inl.position; | |
| } | |
| Handle<SharedFunctionInfo> function( | |
| SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()), isolate); | |
| stack.push_back(SourcePositionInfo(pos, function)); | |
| return stack; | |
| } | |
| void SourcePosition::Print(std::ostream& out, | |
| SharedFunctionInfo* function) const { | |
| Script::PositionInfo pos; | |
| Object* source_name = nullptr; | |
| if (function->script()->IsScript()) { | |
| Script* script = Script::cast(function->script()); | |
| source_name = script->name(); | |
| script->GetPositionInfo(ScriptOffset(), &pos, Script::WITH_OFFSET); | |
| } | |
| out << "<"; | |
| if (source_name != nullptr && source_name->IsString()) { | |
| out << String::cast(source_name) | |
| ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL) | |
| .get(); | |
| } else { | |
| out << "unknown"; | |
| } | |
| out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">"; | |
| } | |
| void SourcePosition::PrintJson(std::ostream& out) const { | |
| out << "{ \"scriptOffset\" : " << ScriptOffset() << ", " | |
| << " \"inliningId\" : " << InliningId() << "}"; | |
| } | |
| void SourcePosition::Print(std::ostream& out, Code* code) const { | |
| DeoptimizationData* deopt_data = | |
| DeoptimizationData::cast(code->deoptimization_data()); | |
| if (!isInlined()) { | |
| SharedFunctionInfo* function( | |
| SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo())); | |
| Print(out, function); | |
| } else { | |
| InliningPosition inl = deopt_data->InliningPositions()->get(InliningId()); | |
| if (inl.inlined_function_id == -1) { | |
| out << *this; | |
| } else { | |
| SharedFunctionInfo* function = | |
| deopt_data->GetInlinedFunction(inl.inlined_function_id); | |
| Print(out, function); | |
| } | |
| out << " inlined at "; | |
| inl.position.Print(out, code); | |
| } | |
| } | |
| SourcePositionInfo::SourcePositionInfo(SourcePosition pos, | |
| Handle<SharedFunctionInfo> f) | |
| : position(pos), | |
| script(f.is_null() || !f->script()->IsScript() | |
| ? Handle<Script>::null() | |
| : handle(Script::cast(f->script()), f->GetIsolate())) { | |
| if (!script.is_null()) { | |
| Script::PositionInfo info; | |
| if (Script::GetPositionInfo(script, pos.ScriptOffset(), &info, | |
| Script::WITH_OFFSET)) { | |
| line = info.line; | |
| column = info.column; | |
| } | |
| } | |
| } | |
| } // namespace internal | |
| } // namespace v8 |