v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
debug-objects.cc
Go to the documentation of this file.
1// Copyright 2017 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
6
12#include "src/utils/ostreams.h"
13
14namespace v8 {
15namespace internal {
16
17bool DebugInfo::IsEmpty() const {
18 return flags(kRelaxedLoad) == kNone && debugger_hints() == 0;
19}
20
22 return (flags(kRelaxedLoad) & kHasBreakInfo) != 0;
23}
24
26 return (flags(kRelaxedLoad) & kDebugExecutionMode) != 0 ? kSideEffects
28}
29
31 set_flags(value == kSideEffects
32 ? (flags(kRelaxedLoad) | kDebugExecutionMode)
33 : (flags(kRelaxedLoad) & ~kDebugExecutionMode),
35}
36
39 // If the function is currently running on the stack, we need to update the
40 // bytecode pointers on the stack so they point to the original
41 // BytecodeArray before releasing that BytecodeArray from this DebugInfo.
42 // Otherwise, it could be flushed and cause problems on resume. See v8:9067.
43 {
44 RedirectActiveFunctions redirect_visitor(
45 isolate, shared(),
47 redirect_visitor.VisitThread(isolate, isolate->thread_local_top());
48 isolate->thread_manager()->IterateArchivedThreads(&redirect_visitor);
49 }
50
52 }
53 set_break_points(ReadOnlyRoots(isolate).empty_fixed_array());
54
55 int new_flags = flags(kRelaxedLoad);
56 new_flags &= ~kHasBreakInfo & ~kPreparedForDebugExecution;
57 new_flags &= ~kBreakAtEntry & ~kCanBreakAtEntry;
58 new_flags &= ~kDebugExecutionMode;
59 set_flags(new_flags, kRelaxedStore);
60}
61
64 set_flags(flags(kRelaxedLoad) | kBreakAtEntry, kRelaxedStore);
65}
66
69 set_flags(flags(kRelaxedLoad) & ~kBreakAtEntry, kRelaxedStore);
70}
71
73 return (flags(kRelaxedLoad) & kBreakAtEntry) != 0;
74}
75
77 return (flags(kRelaxedLoad) & kCanBreakAtEntry) != 0;
78}
79
80// Check if there is a break point at this source position.
81bool DebugInfo::HasBreakPoint(Isolate* isolate, int source_position) {
83 // Get the break point info object for this code offset.
84 Tagged<Object> break_point_info = GetBreakPointInfo(isolate, source_position);
85
86 // If there is no break point info object or no break points in the break
87 // point info object there is no break point at this code offset.
88 if (IsUndefined(break_point_info, isolate)) return false;
89 return Cast<BreakPointInfo>(break_point_info)->GetBreakPointCount(isolate) >
90 0;
91}
92
93// Get the break point info object for this source position.
95 int source_position) {
97 for (int i = 0; i < break_points()->length(); i++) {
98 if (!IsUndefined(break_points()->get(i), isolate)) {
99 Tagged<BreakPointInfo> break_point_info =
100 Cast<BreakPointInfo>(break_points()->get(i));
101 if (break_point_info->source_position() == source_position) {
102 return break_point_info;
103 }
104 }
105 }
106 return ReadOnlyRoots(isolate).undefined_value();
107}
108
110 DirectHandle<DebugInfo> debug_info,
111 DirectHandle<BreakPoint> break_point) {
112 DCHECK(debug_info->HasBreakInfo());
113 for (int i = 0; i < debug_info->break_points()->length(); i++) {
114 if (IsUndefined(debug_info->break_points()->get(i), isolate)) continue;
115 DirectHandle<BreakPointInfo> break_point_info(
116 Cast<BreakPointInfo>(debug_info->break_points()->get(i)), isolate);
117 if (BreakPointInfo::HasBreakPoint(isolate, break_point_info, break_point)) {
118 BreakPointInfo::ClearBreakPoint(isolate, break_point_info, break_point);
119 return true;
120 }
121 }
122 return false;
123}
124
126 DirectHandle<DebugInfo> debug_info,
127 int source_position,
128 DirectHandle<BreakPoint> break_point) {
129 DCHECK(debug_info->HasBreakInfo());
130 DirectHandle<Object> break_point_info(
131 debug_info->GetBreakPointInfo(isolate, source_position), isolate);
132 if (!IsUndefined(*break_point_info, isolate)) {
134 isolate, Cast<BreakPointInfo>(break_point_info), break_point);
135 return;
136 }
137
138 // Adding a new break point for a code offset which did not have any
139 // break points before. Try to find a free slot.
140 static const int kNoBreakPointInfo = -1;
141 int index = kNoBreakPointInfo;
142 for (int i = 0; i < debug_info->break_points()->length(); i++) {
143 if (IsUndefined(debug_info->break_points()->get(i), isolate)) {
144 index = i;
145 break;
146 }
147 }
148 if (index == kNoBreakPointInfo) {
149 // No free slot - extend break point info array.
150 DirectHandle<FixedArray> old_break_points(debug_info->break_points(),
151 isolate);
152 DirectHandle<FixedArray> new_break_points =
153 isolate->factory()->NewFixedArray(
154 old_break_points->length() +
156
157 debug_info->set_break_points(*new_break_points);
158 for (int i = 0; i < old_break_points->length(); i++) {
159 new_break_points->set(i, old_break_points->get(i));
160 }
161 index = old_break_points->length();
162 }
163 DCHECK_NE(index, kNoBreakPointInfo);
164
165 // Allocate new BreakPointInfo object and set the break point.
166 DirectHandle<BreakPointInfo> new_break_point_info =
167 isolate->factory()->NewBreakPointInfo(source_position);
168 BreakPointInfo::SetBreakPoint(isolate, new_break_point_info, break_point);
169 debug_info->break_points()->set(index, *new_break_point_info);
170}
171
172// Get the break point objects for a source position.
174 int source_position) {
176 Tagged<Object> break_point_info = GetBreakPointInfo(isolate, source_position);
177 if (IsUndefined(break_point_info, isolate)) {
178 return isolate->factory()->undefined_value();
179 }
181 Cast<BreakPointInfo>(break_point_info)->break_points(), isolate);
182}
183
184// Get the total number of break points.
187 int count = 0;
188 for (int i = 0; i < break_points()->length(); i++) {
189 if (!IsUndefined(break_points()->get(i), isolate)) {
190 Tagged<BreakPointInfo> break_point_info =
191 Cast<BreakPointInfo>(break_points()->get(i));
192 count += break_point_info->GetBreakPointCount(isolate);
193 }
194 }
195 return count;
196}
197
199 Isolate* isolate, DirectHandle<DebugInfo> debug_info,
200 DirectHandle<BreakPoint> break_point) {
201 DCHECK(debug_info->HasBreakInfo());
202 for (int i = 0; i < debug_info->break_points()->length(); i++) {
203 if (!IsUndefined(debug_info->break_points()->get(i), isolate)) {
204 DirectHandle<BreakPointInfo> break_point_info(
205 Cast<BreakPointInfo>(debug_info->break_points()->get(i)), isolate);
206 if (BreakPointInfo::HasBreakPoint(isolate, break_point_info,
207 break_point)) {
208 return break_point_info;
209 }
210 }
211 }
212 return isolate->factory()->undefined_value();
213}
214
216 return (flags(kRelaxedLoad) & kHasCoverageInfo) != 0;
217}
218
220 if (HasCoverageInfo()) {
221 set_coverage_info(ReadOnlyRoots(isolate).undefined_value());
222
223 int new_flags = flags(kRelaxedLoad) & ~kHasCoverageInfo;
224 set_flags(new_flags, kRelaxedStore);
225 }
226}
227
229 if (side_effect_state() == kNotComputed) {
230 SideEffectState has_no_side_effect =
232 isolate, direct_handle(shared(), isolate));
233 set_side_effect_state(has_no_side_effect);
234 }
235 return static_cast<SideEffectState>(side_effect_state());
236}
237
238namespace {
239bool IsEqual(Tagged<BreakPoint> break_point1, Tagged<BreakPoint> break_point2) {
240 return break_point1->id() == break_point2->id();
241}
242} // namespace
243
244// Remove the specified break point object.
246 Isolate* isolate, DirectHandle<BreakPointInfo> break_point_info,
247 DirectHandle<BreakPoint> break_point) {
248 // If there are no break points just ignore.
249 if (IsUndefined(break_point_info->break_points(), isolate)) return;
250 // If there is a single break point clear it if it is the same.
251 if (!IsFixedArray(break_point_info->break_points())) {
252 if (IsEqual(Cast<BreakPoint>(break_point_info->break_points()),
253 *break_point)) {
254 break_point_info->set_break_points(
255 ReadOnlyRoots(isolate).undefined_value());
256 }
257 return;
258 }
259 // If there are multiple break points shrink the array
260 DCHECK(IsFixedArray(break_point_info->break_points()));
261 DirectHandle<FixedArray> old_array(
262 Cast<FixedArray>(break_point_info->break_points()), isolate);
263 DirectHandle<FixedArray> new_array =
264 isolate->factory()->NewFixedArray(old_array->length() - 1);
265 int found_count = 0;
266 for (int i = 0; i < old_array->length(); i++) {
267 if (IsEqual(Cast<BreakPoint>(old_array->get(i)), *break_point)) {
268 DCHECK_EQ(found_count, 0);
269 found_count++;
270 } else {
271 new_array->set(i - found_count, old_array->get(i));
272 }
273 }
274 // If the break point was found in the list change it.
275 if (found_count > 0) break_point_info->set_break_points(*new_array);
276}
277
278// Add the specified break point object.
280 Isolate* isolate, DirectHandle<BreakPointInfo> break_point_info,
281 DirectHandle<BreakPoint> break_point) {
282 // If there was no break point objects before just set it.
283 if (IsUndefined(break_point_info->break_points(), isolate)) {
284 break_point_info->set_break_points(*break_point);
285 return;
286 }
287 // If there was one break point object before replace with array.
288 if (!IsFixedArray(break_point_info->break_points())) {
289 if (IsEqual(Cast<BreakPoint>(break_point_info->break_points()),
290 *break_point)) {
291 return;
292 }
293
294 DirectHandle<FixedArray> array = isolate->factory()->NewFixedArray(2);
295 array->set(0, break_point_info->break_points());
296 array->set(1, *break_point);
297 break_point_info->set_break_points(*array);
298 return;
299 }
300 // If there was more than one break point before extend array.
301 DirectHandle<FixedArray> old_array(
302 Cast<FixedArray>(break_point_info->break_points()), isolate);
303 DirectHandle<FixedArray> new_array =
304 isolate->factory()->NewFixedArray(old_array->length() + 1);
305 for (int i = 0; i < old_array->length(); i++) {
306 // If the break point was there before just ignore.
307 if (IsEqual(Cast<BreakPoint>(old_array->get(i)), *break_point)) return;
308 new_array->set(i, old_array->get(i));
309 }
310 // Add the new break point.
311 new_array->set(old_array->length(), *break_point);
312 break_point_info->set_break_points(*new_array);
313}
314
316 Isolate* isolate, DirectHandle<BreakPointInfo> break_point_info,
317 DirectHandle<BreakPoint> break_point) {
318 // No break point.
319 if (IsUndefined(break_point_info->break_points(), isolate)) {
320 return false;
321 }
322 // Single break point.
323 if (!IsFixedArray(break_point_info->break_points())) {
324 return IsEqual(Cast<BreakPoint>(break_point_info->break_points()),
325 *break_point);
326 }
327 // Multiple break points.
328 Tagged<FixedArray> array = Cast<FixedArray>(break_point_info->break_points());
329 for (int i = 0; i < array->length(); i++) {
330 if (IsEqual(Cast<BreakPoint>(array->get(i)), *break_point)) {
331 return true;
332 }
333 }
334 return false;
335}
336
338 Isolate* isolate, DirectHandle<BreakPointInfo> break_point_info,
339 int breakpoint_id) {
340 // No break point.
341 if (IsUndefined(break_point_info->break_points(), isolate)) {
343 }
344 // Single break point.
345 if (!IsFixedArray(break_point_info->break_points())) {
346 Tagged<BreakPoint> breakpoint =
347 Cast<BreakPoint>(break_point_info->break_points());
348 if (breakpoint->id() == breakpoint_id) {
349 return direct_handle(breakpoint, isolate);
350 }
351 } else {
352 // Multiple break points.
353 Tagged<FixedArray> array =
354 Cast<FixedArray>(break_point_info->break_points());
355 for (int i = 0; i < array->length(); i++) {
356 Tagged<BreakPoint> breakpoint = Cast<BreakPoint>(array->get(i));
357 if (breakpoint->id() == breakpoint_id) {
358 return direct_handle(breakpoint, isolate);
359 }
360 }
361 }
363}
364
365// Get the number of break points.
367 // No break point.
368 if (IsUndefined(break_points(), isolate)) return 0;
369 // Single break point.
370 if (!IsFixedArray(break_points())) return 1;
371 // Multiple break points.
372 return Cast<FixedArray>(break_points())->length();
373}
374
375void CoverageInfo::InitializeSlot(int slot_index, int from_pos, int to_pos) {
376 set_slots_start_source_position(slot_index, from_pos);
377 set_slots_end_source_position(slot_index, to_pos);
378 ResetBlockCount(slot_index);
379 set_slots_padding(slot_index, 0);
380}
381
382void CoverageInfo::ResetBlockCount(int slot_index) {
383 set_slots_block_count(slot_index, 0);
384}
385
387 std::unique_ptr<char[]> function_name) {
389
390 os << "Coverage info (";
391 if (function_name == nullptr) {
392 os << "{unknown}";
393 } else if (strlen(function_name.get()) > 0) {
394 os << function_name.get();
395 } else {
396 os << "{anonymous}";
397 }
398 os << "):" << std::endl;
399
400 for (int i = 0; i < slot_count(); i++) {
401 os << "{" << slots_start_source_position(i) << ","
402 << slots_end_source_position(i) << "}" << std::endl;
403 }
404}
405
406// static
408 if (IsScript(info->shared_or_script())) {
409 return info->bytecode_offset_or_source_position();
410 }
411 Isolate* isolate = info->GetIsolate();
413 Cast<SharedFunctionInfo>(info->shared_or_script()), isolate);
415 int source_position = shared->abstract_code(isolate)->SourcePosition(
416 isolate, info->bytecode_offset_or_source_position());
417 info->set_shared_or_script(Cast<Script>(shared->script()));
418 info->set_bytecode_offset_or_source_position(source_position);
419 return source_position;
420}
421
422int StackTraceInfo::length() const { return frames()->length(); }
423
425 return Cast<StackFrameInfo>(frames()->get(index));
426}
427
428} // namespace internal
429} // namespace v8
static void SetBreakPoint(Isolate *isolate, DirectHandle< BreakPointInfo > info, DirectHandle< BreakPoint > break_point)
int GetBreakPointCount(Isolate *isolate)
static bool HasBreakPoint(Isolate *isolate, DirectHandle< BreakPointInfo > info, DirectHandle< BreakPoint > break_point)
static void ClearBreakPoint(Isolate *isolate, DirectHandle< BreakPointInfo > info, DirectHandle< BreakPoint > break_point)
static MaybeDirectHandle< BreakPoint > GetBreakPointById(Isolate *isolate, DirectHandle< BreakPointInfo > info, int breakpoint_id)
void InitializeSlot(int slot_index, int start_pos, int end_pos)
void ResetBlockCount(int slot_index)
void CoverageInfoPrint(std::ostream &os, std::unique_ptr< char[]> function_name=nullptr)
static DebugInfo::SideEffectState FunctionGetSideEffectState(Isolate *isolate, DirectHandle< SharedFunctionInfo > info)
static const int kEstimatedNofBreakPointsInFunction
bool HasBreakPoint(Isolate *isolate, int source_position)
V8_EXPORT_PRIVATE void ClearBreakInfo(Isolate *isolate)
static bool ClearBreakPoint(Isolate *isolate, DirectHandle< DebugInfo > debug_info, DirectHandle< BreakPoint > break_point)
static DirectHandle< Object > FindBreakPointInfo(Isolate *isolate, DirectHandle< DebugInfo > debug_info, DirectHandle< BreakPoint > break_point)
void SetDebugExecutionMode(ExecutionMode value)
DirectHandle< Object > GetBreakPoints(Isolate *isolate, int source_position)
void ClearCoverageInfo(Isolate *isolate)
Tagged< Object > GetBreakPointInfo(Isolate *isolate, int source_position)
NEVER_READ_ONLY_SPACE bool IsEmpty() const
SideEffectState GetSideEffectState(Isolate *isolate)
ExecutionMode DebugExecutionMode() const
static void SetBreakPoint(Isolate *isolate, DirectHandle< DebugInfo > debug_info, int source_position, DirectHandle< BreakPoint > break_point)
int GetBreakPointCount(Isolate *isolate)
void VisitThread(Isolate *isolate, ThreadLocalTop *top) override
static void UninstallDebugBytecode(Tagged< SharedFunctionInfo > shared, Isolate *isolate)
static void EnsureSourcePositionsAvailable(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared_info)
static NEVER_READ_ONLY_SPACE int GetSourcePosition(DirectHandle< StackFrameInfo > info)
NEVER_READ_ONLY_SPACE int length() const
Tagged< StackFrameInfo > get(int index) const
uint32_t count
SharedFunctionInfoRef shared
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
Flag flags[]
Definition flags.cc:3797
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
static constexpr RelaxedLoadTag kRelaxedLoad
Definition globals.h:2909
static constexpr RelaxedStoreTag kRelaxedStore
Definition globals.h:2911
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485