1// Copyright 2016 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/codegen/source-position.h" 6#include "src/codegen/optimized-compilation-info.h" 7#include "src/objects/objects-inl.h" 8 9namespace v8 { 10namespace internal { 11 12std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos) { 13 out << "<"; 14 if (!pos.script.is_null() && pos.script->name().IsString()) { 15 out << String::cast(pos.script->name()).ToCString(DISALLOW_NULLS).get(); 16 } else { 17 out << "unknown"; 18 } 19 out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">"; 20 return out; 21} 22 23std::ostream& operator<<(std::ostream& out, 24 const std::vector<SourcePositionInfo>& stack) { 25 bool first = true; 26 for (const SourcePositionInfo& pos : stack) { 27 if (!first) out << " inlined at "; 28 out << pos; 29 first = false; 30 } 31 return out; 32} 33 34std::ostream& operator<<(std::ostream& out, const SourcePosition& pos) { 35 if (pos.isInlined()) { 36 out << "<inlined(" << pos.InliningId() << "):"; 37 } else { 38 out << "<not inlined:"; 39 } 40 41 if (pos.IsExternal()) { 42 out << pos.ExternalLine() << ", " << pos.ExternalFileId() << ">"; 43 } else { 44 out << pos.ScriptOffset() << ">"; 45 } 46 return out; 47} 48 49std::vector<SourcePositionInfo> SourcePosition::InliningStack( 50 OptimizedCompilationInfo* cinfo) const { 51 SourcePosition pos = *this; 52 std::vector<SourcePositionInfo> stack; 53 while (pos.isInlined()) { 54 const auto& inl = cinfo->inlined_functions()[pos.InliningId()]; 55 stack.push_back(SourcePositionInfo(pos, inl.shared_info)); 56 pos = inl.position.position; 57 } 58 stack.push_back(SourcePositionInfo(pos, cinfo->shared_info())); 59 return stack; 60} 61 62std::vector<SourcePositionInfo> SourcePosition::InliningStack( 63 Handle<Code> code) const { 64 Isolate* isolate = code->GetIsolate(); 65 DeoptimizationData deopt_data = 66 DeoptimizationData::cast(code->deoptimization_data()); 67 SourcePosition pos = *this; 68 std::vector<SourcePositionInfo> stack; 69 while (pos.isInlined()) { 70 InliningPosition inl = deopt_data.InliningPositions().get(pos.InliningId()); 71 Handle<SharedFunctionInfo> function( 72 deopt_data.GetInlinedFunction(inl.inlined_function_id), isolate); 73 stack.push_back(SourcePositionInfo(pos, function)); 74 pos = inl.position; 75 } 76 Handle<SharedFunctionInfo> function( 77 SharedFunctionInfo::cast(deopt_data.SharedFunctionInfo()), isolate); 78 stack.push_back(SourcePositionInfo(pos, function)); 79 return stack; 80} 81 82SourcePositionInfo SourcePosition::FirstInfo(Handle<Code> code) const { 83 DisallowGarbageCollection no_gc; 84 Isolate* isolate = code->GetIsolate(); 85 DeoptimizationData deopt_data = 86 DeoptimizationData::cast(code->deoptimization_data()); 87 SourcePosition pos = *this; 88 if (pos.isInlined()) { 89 InliningPosition inl = deopt_data.InliningPositions().get(pos.InliningId()); 90 Handle<SharedFunctionInfo> function( 91 deopt_data.GetInlinedFunction(inl.inlined_function_id), isolate); 92 return SourcePositionInfo(pos, function); 93 } 94 Handle<SharedFunctionInfo> function( 95 SharedFunctionInfo::cast(deopt_data.SharedFunctionInfo()), isolate); 96 return SourcePositionInfo(pos, function); 97} 98 99void SourcePosition::Print(std::ostream& out, 100 SharedFunctionInfo function) const { 101 Script::PositionInfo pos; 102 Object source_name; 103 if (function.script().IsScript()) { 104 Script script = Script::cast(function.script()); 105 source_name = script.name(); 106 script.GetPositionInfo(ScriptOffset(), &pos, Script::WITH_OFFSET); 107 } 108 out << "<"; 109 if (source_name.IsString()) { 110 out << String::cast(source_name) 111 .ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL) 112 .get(); 113 } else { 114 out << "unknown"; 115 } 116 out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">"; 117} 118 119void SourcePosition::PrintJson(std::ostream& out) const { 120 if (IsExternal()) { 121 out << "{ \"line\" : " << ExternalLine() << ", " 122 << " \"fileId\" : " << ExternalFileId() << ", " 123 << " \"inliningId\" : " << InliningId() << "}"; 124 } else { 125 out << "{ \"scriptOffset\" : " << ScriptOffset() << ", " 126 << " \"inliningId\" : " << InliningId() << "}"; 127 } 128} 129 130void SourcePosition::Print(std::ostream& out, Code code) const { 131 DeoptimizationData deopt_data = 132 DeoptimizationData::cast(code.deoptimization_data()); 133 if (!isInlined()) { 134 SharedFunctionInfo function( 135 SharedFunctionInfo::cast(deopt_data.SharedFunctionInfo())); 136 Print(out, function); 137 } else { 138 InliningPosition inl = deopt_data.InliningPositions().get(InliningId()); 139 if (inl.inlined_function_id == -1) { 140 out << *this; 141 } else { 142 SharedFunctionInfo function = 143 deopt_data.GetInlinedFunction(inl.inlined_function_id); 144 Print(out, function); 145 } 146 out << " inlined at "; 147 inl.position.Print(out, code); 148 } 149} 150 151SourcePositionInfo::SourcePositionInfo(SourcePosition pos, 152 Handle<SharedFunctionInfo> f) 153 : position(pos), 154 shared(f), 155 script(f.is_null() || !f->script().IsScript() 156 ? Handle<Script>::null() 157 : handle(Script::cast(f->script()), f->GetIsolate())) { 158 if (!script.is_null()) { 159 Script::PositionInfo info; 160 if (Script::GetPositionInfo(script, pos.ScriptOffset(), &info, 161 Script::WITH_OFFSET)) { 162 line = info.line; 163 column = info.column; 164 } 165 } 166} 167 168} // namespace internal 169} // namespace v8 170