Line data Source code
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 :
5 : #include "src/objects/debug-objects.h"
6 :
7 : #include "src/debug/debug-evaluate.h"
8 : #include "src/handles-inl.h"
9 : #include "src/objects/debug-objects-inl.h"
10 : #include "src/ostreams.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 58905 : bool DebugInfo::IsEmpty() const {
16 117622 : return flags() == kNone && debugger_hints() == 0;
17 : }
18 :
19 3270040 : bool DebugInfo::HasBreakInfo() const { return (flags() & kHasBreakInfo) != 0; }
20 :
21 13115 : DebugInfo::ExecutionMode DebugInfo::DebugExecutionMode() const {
22 13115 : return (flags() & kDebugExecutionMode) != 0 ? kSideEffects : kBreakpoints;
23 : }
24 :
25 1145873 : void DebugInfo::SetDebugExecutionMode(ExecutionMode value) {
26 2291746 : set_flags(value == kSideEffects ? (flags() | kDebugExecutionMode)
27 : : (flags() & ~kDebugExecutionMode));
28 1145873 : }
29 :
30 28435 : void DebugInfo::ClearBreakInfo(Isolate* isolate) {
31 28435 : if (HasInstrumentedBytecodeArray()) {
32 : // Reset function's bytecode array field to point to the original bytecode
33 : // array.
34 10601 : shared()->SetDebugBytecodeArray(OriginalBytecodeArray());
35 :
36 : // If the function is currently running on the stack, we need to update the
37 : // bytecode pointers on the stack so they point to the original
38 : // BytecodeArray before releasing that BytecodeArray from this DebugInfo.
39 : // Otherwise, it could be flushed and cause problems on resume. See v8:9067.
40 : {
41 : RedirectActiveFunctions redirect_visitor(
42 10601 : shared(), RedirectActiveFunctions::Mode::kUseOriginalBytecode);
43 10601 : redirect_visitor.VisitThread(isolate, isolate->thread_local_top());
44 10601 : isolate->thread_manager()->IterateArchivedThreads(&redirect_visitor);
45 : }
46 :
47 10601 : set_original_bytecode_array(ReadOnlyRoots(isolate).undefined_value());
48 10601 : set_debug_bytecode_array(ReadOnlyRoots(isolate).undefined_value());
49 : }
50 28435 : set_break_points(ReadOnlyRoots(isolate).empty_fixed_array());
51 :
52 : int new_flags = flags();
53 : new_flags &= ~kHasBreakInfo & ~kPreparedForDebugExecution;
54 : new_flags &= ~kBreakAtEntry & ~kCanBreakAtEntry;
55 28435 : new_flags &= ~kDebugExecutionMode;
56 : set_flags(new_flags);
57 28435 : }
58 :
59 595 : void DebugInfo::SetBreakAtEntry() {
60 : DCHECK(CanBreakAtEntry());
61 595 : set_flags(flags() | kBreakAtEntry);
62 595 : }
63 :
64 745 : void DebugInfo::ClearBreakAtEntry() {
65 : DCHECK(CanBreakAtEntry());
66 745 : set_flags(flags() & ~kBreakAtEntry);
67 745 : }
68 :
69 10008 : bool DebugInfo::BreakAtEntry() const { return (flags() & kBreakAtEntry) != 0; }
70 :
71 3080032 : bool DebugInfo::CanBreakAtEntry() const {
72 3080032 : return (flags() & kCanBreakAtEntry) != 0;
73 : }
74 :
75 : // Check if there is a break point at this source position.
76 186876 : bool DebugInfo::HasBreakPoint(Isolate* isolate, int source_position) {
77 : DCHECK(HasBreakInfo());
78 : // Get the break point info object for this code offset.
79 186876 : Object break_point_info = GetBreakPointInfo(isolate, source_position);
80 :
81 : // If there is no break point info object or no break points in the break
82 : // point info object there is no break point at this code offset.
83 186876 : if (break_point_info->IsUndefined(isolate)) return false;
84 8576 : return BreakPointInfo::cast(break_point_info)->GetBreakPointCount(isolate) >
85 4288 : 0;
86 : }
87 :
88 : // Get the break point info object for this source position.
89 193570 : Object DebugInfo::GetBreakPointInfo(Isolate* isolate, int source_position) {
90 : DCHECK(HasBreakInfo());
91 1675174 : for (int i = 0; i < break_points()->length(); i++) {
92 749424 : if (!break_points()->get(i)->IsUndefined(isolate)) {
93 : BreakPointInfo break_point_info =
94 : BreakPointInfo::cast(break_points()->get(i));
95 40554 : if (break_point_info->source_position() == source_position) {
96 8622 : return break_point_info;
97 : }
98 : }
99 : }
100 184948 : return ReadOnlyRoots(isolate).undefined_value();
101 : }
102 :
103 2302 : bool DebugInfo::ClearBreakPoint(Isolate* isolate, Handle<DebugInfo> debug_info,
104 : Handle<BreakPoint> break_point) {
105 : DCHECK(debug_info->HasBreakInfo());
106 3504 : for (int i = 0; i < debug_info->break_points()->length(); i++) {
107 2903 : if (debug_info->break_points()->get(i)->IsUndefined(isolate)) continue;
108 : Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
109 : BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
110 2903 : if (BreakPointInfo::HasBreakPoint(isolate, break_point_info, break_point)) {
111 2302 : BreakPointInfo::ClearBreakPoint(isolate, break_point_info, break_point);
112 2302 : return true;
113 : }
114 : }
115 : return false;
116 : }
117 :
118 2492 : void DebugInfo::SetBreakPoint(Isolate* isolate, Handle<DebugInfo> debug_info,
119 : int source_position,
120 : Handle<BreakPoint> break_point) {
121 : DCHECK(debug_info->HasBreakInfo());
122 : Handle<Object> break_point_info(
123 4984 : debug_info->GetBreakPointInfo(isolate, source_position), isolate);
124 2492 : if (!break_point_info->IsUndefined(isolate)) {
125 : BreakPointInfo::SetBreakPoint(
126 132 : isolate, Handle<BreakPointInfo>::cast(break_point_info), break_point);
127 132 : return;
128 : }
129 :
130 : // Adding a new break point for a code offset which did not have any
131 : // break points before. Try to find a free slot.
132 : static const int kNoBreakPointInfo = -1;
133 : int index = kNoBreakPointInfo;
134 3558 : for (int i = 0; i < debug_info->break_points()->length(); i++) {
135 2945 : if (debug_info->break_points()->get(i)->IsUndefined(isolate)) {
136 : index = i;
137 : break;
138 : }
139 : }
140 2360 : if (index == kNoBreakPointInfo) {
141 : // No free slot - extend break point info array.
142 : Handle<FixedArray> old_break_points =
143 : Handle<FixedArray>(debug_info->break_points(), isolate);
144 : Handle<FixedArray> new_break_points = isolate->factory()->NewFixedArray(
145 : old_break_points->length() +
146 14 : DebugInfo::kEstimatedNofBreakPointsInFunction);
147 :
148 14 : debug_info->set_break_points(*new_break_points);
149 126 : for (int i = 0; i < old_break_points->length(); i++) {
150 56 : new_break_points->set(i, old_break_points->get(i));
151 : }
152 : index = old_break_points->length();
153 : }
154 : DCHECK_NE(index, kNoBreakPointInfo);
155 :
156 : // Allocate new BreakPointInfo object and set the break point.
157 : Handle<BreakPointInfo> new_break_point_info =
158 2360 : isolate->factory()->NewBreakPointInfo(source_position);
159 2360 : BreakPointInfo::SetBreakPoint(isolate, new_break_point_info, break_point);
160 4720 : debug_info->break_points()->set(index, *new_break_point_info);
161 : }
162 :
163 : // Get the break point objects for a source position.
164 4202 : Handle<Object> DebugInfo::GetBreakPoints(Isolate* isolate,
165 : int source_position) {
166 : DCHECK(HasBreakInfo());
167 4202 : Object break_point_info = GetBreakPointInfo(isolate, source_position);
168 4202 : if (break_point_info->IsUndefined(isolate)) {
169 0 : return isolate->factory()->undefined_value();
170 : }
171 : return Handle<Object>(BreakPointInfo::cast(break_point_info)->break_points(),
172 4202 : isolate);
173 : }
174 :
175 : // Get the total number of break points.
176 3130 : int DebugInfo::GetBreakPointCount(Isolate* isolate) {
177 : DCHECK(HasBreakInfo());
178 : int count = 0;
179 29242 : for (int i = 0; i < break_points()->length(); i++) {
180 13056 : if (!break_points()->get(i)->IsUndefined(isolate)) {
181 : BreakPointInfo break_point_info =
182 5434 : BreakPointInfo::cast(break_points()->get(i));
183 5434 : count += break_point_info->GetBreakPointCount(isolate);
184 : }
185 : }
186 3130 : return count;
187 : }
188 :
189 8019 : Handle<Object> DebugInfo::FindBreakPointInfo(Isolate* isolate,
190 : Handle<DebugInfo> debug_info,
191 : Handle<BreakPoint> break_point) {
192 : DCHECK(debug_info->HasBreakInfo());
193 55541 : for (int i = 0; i < debug_info->break_points()->length(); i++) {
194 26063 : if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
195 : Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
196 : BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
197 4800 : if (BreakPointInfo::HasBreakPoint(isolate, break_point_info,
198 : break_point)) {
199 2302 : return break_point_info;
200 : }
201 : }
202 : }
203 5717 : return isolate->factory()->undefined_value();
204 : }
205 :
206 192428 : bool DebugInfo::HasCoverageInfo() const {
207 208111 : return (flags() & kHasCoverageInfo) != 0;
208 : }
209 :
210 15683 : void DebugInfo::ClearCoverageInfo(Isolate* isolate) {
211 15683 : if (HasCoverageInfo()) {
212 880 : set_coverage_info(ReadOnlyRoots(isolate).undefined_value());
213 :
214 880 : int new_flags = flags() & ~kHasCoverageInfo;
215 : set_flags(new_flags);
216 : }
217 15683 : }
218 :
219 13869 : DebugInfo::SideEffectState DebugInfo::GetSideEffectState(Isolate* isolate) {
220 13869 : if (side_effect_state() == kNotComputed) {
221 : SideEffectState has_no_side_effect =
222 : DebugEvaluate::FunctionGetSideEffectState(isolate,
223 12255 : handle(shared(), isolate));
224 12255 : set_side_effect_state(has_no_side_effect);
225 : }
226 13869 : return static_cast<SideEffectState>(side_effect_state());
227 : }
228 :
229 : namespace {
230 : bool IsEqual(BreakPoint break_point1, BreakPoint break_point2) {
231 6478 : return break_point1->id() == break_point2->id();
232 : }
233 : } // namespace
234 :
235 : // Remove the specified break point object.
236 2302 : void BreakPointInfo::ClearBreakPoint(Isolate* isolate,
237 : Handle<BreakPointInfo> break_point_info,
238 : Handle<BreakPoint> break_point) {
239 : // If there are no break points just ignore.
240 2302 : if (break_point_info->break_points()->IsUndefined(isolate)) return;
241 : // If there is a single break point clear it if it is the same.
242 2302 : if (!break_point_info->break_points()->IsFixedArray()) {
243 2143 : if (IsEqual(BreakPoint::cast(break_point_info->break_points()),
244 : *break_point)) {
245 4286 : break_point_info->set_break_points(
246 6429 : ReadOnlyRoots(isolate).undefined_value());
247 : }
248 : return;
249 : }
250 : // If there are multiple break points shrink the array
251 : DCHECK(break_point_info->break_points()->IsFixedArray());
252 : Handle<FixedArray> old_array = Handle<FixedArray>(
253 : FixedArray::cast(break_point_info->break_points()), isolate);
254 : Handle<FixedArray> new_array =
255 159 : isolate->factory()->NewFixedArray(old_array->length() - 1);
256 : int found_count = 0;
257 2109 : for (int i = 0; i < old_array->length(); i++) {
258 975 : if (IsEqual(BreakPoint::cast(old_array->get(i)), *break_point)) {
259 : DCHECK_EQ(found_count, 0);
260 159 : found_count++;
261 : } else {
262 1632 : new_array->set(i - found_count, old_array->get(i));
263 : }
264 : }
265 : // If the break point was found in the list change it.
266 477 : if (found_count > 0) break_point_info->set_break_points(*new_array);
267 : }
268 :
269 : // Add the specified break point object.
270 2608 : void BreakPointInfo::SetBreakPoint(Isolate* isolate,
271 : Handle<BreakPointInfo> break_point_info,
272 : Handle<BreakPoint> break_point) {
273 : // If there was no break point objects before just set it.
274 2608 : if (break_point_info->break_points()->IsUndefined(isolate)) {
275 2476 : break_point_info->set_break_points(*break_point);
276 2476 : return;
277 : }
278 : // If the break point object is the same as before just ignore.
279 132 : if (break_point_info->break_points() == *break_point) return;
280 : // If there was one break point object before replace with array.
281 132 : if (!break_point_info->break_points()->IsFixedArray()) {
282 27 : Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
283 27 : array->set(0, break_point_info->break_points());
284 54 : array->set(1, *break_point);
285 54 : break_point_info->set_break_points(*array);
286 : return;
287 : }
288 : // If there was more than one break point before extend array.
289 : Handle<FixedArray> old_array = Handle<FixedArray>(
290 : FixedArray::cast(break_point_info->break_points()), isolate);
291 : Handle<FixedArray> new_array =
292 105 : isolate->factory()->NewFixedArray(old_array->length() + 1);
293 1683 : for (int i = 0; i < old_array->length(); i++) {
294 : // If the break point was there before just ignore.
295 789 : if (IsEqual(BreakPoint::cast(old_array->get(i)), *break_point)) return;
296 789 : new_array->set(i, old_array->get(i));
297 : }
298 : // Add the new break point.
299 210 : new_array->set(old_array->length(), *break_point);
300 210 : break_point_info->set_break_points(*new_array);
301 : }
302 :
303 7703 : bool BreakPointInfo::HasBreakPoint(Isolate* isolate,
304 : Handle<BreakPointInfo> break_point_info,
305 : Handle<BreakPoint> break_point) {
306 : // No break point.
307 7703 : if (break_point_info->break_points()->IsUndefined(isolate)) {
308 : return false;
309 : }
310 : // Single break point.
311 6876 : if (!break_point_info->break_points()->IsFixedArray()) {
312 : return IsEqual(BreakPoint::cast(break_point_info->break_points()),
313 : *break_point);
314 : }
315 : // Multiple break points.
316 : FixedArray array = FixedArray::cast(break_point_info->break_points());
317 2454 : for (int i = 0; i < array->length(); i++) {
318 1346 : if (IsEqual(BreakPoint::cast(array->get(i)), *break_point)) {
319 : return true;
320 : }
321 : }
322 : return false;
323 : }
324 :
325 : // Get the number of break points.
326 78560 : int BreakPointInfo::GetBreakPointCount(Isolate* isolate) {
327 : // No break point.
328 78560 : if (break_points()->IsUndefined(isolate)) return 0;
329 : // Single break point.
330 74495 : if (!break_points()->IsFixedArray()) return 1;
331 : // Multiple break points.
332 : return FixedArray::cast(break_points())->length();
333 : }
334 :
335 124868 : int CoverageInfo::SlotCount() const {
336 : DCHECK_EQ(kFirstSlotIndex, length() % kSlotIndexCount);
337 124868 : return (length() - kFirstSlotIndex) / kSlotIndexCount;
338 : }
339 :
340 46264 : int CoverageInfo::StartSourcePosition(int slot_index) const {
341 : DCHECK_LT(slot_index, SlotCount());
342 : const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
343 46264 : return Smi::ToInt(get(slot_start + kSlotStartSourcePositionIndex));
344 : }
345 :
346 46264 : int CoverageInfo::EndSourcePosition(int slot_index) const {
347 : DCHECK_LT(slot_index, SlotCount());
348 : const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
349 92528 : return Smi::ToInt(get(slot_start + kSlotEndSourcePositionIndex));
350 : }
351 :
352 46264 : int CoverageInfo::BlockCount(int slot_index) const {
353 : DCHECK_LT(slot_index, SlotCount());
354 : const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
355 272028 : return Smi::ToInt(get(slot_start + kSlotBlockCountIndex));
356 : }
357 :
358 2268 : void CoverageInfo::InitializeSlot(int slot_index, int from_pos, int to_pos) {
359 : DCHECK_LT(slot_index, SlotCount());
360 : const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
361 : set(slot_start + kSlotStartSourcePositionIndex, Smi::FromInt(from_pos));
362 : set(slot_start + kSlotEndSourcePositionIndex, Smi::FromInt(to_pos));
363 2268 : set(slot_start + kSlotBlockCountIndex, Smi::kZero);
364 2268 : }
365 :
366 179500 : void CoverageInfo::IncrementBlockCount(int slot_index) {
367 : DCHECK_LT(slot_index, SlotCount());
368 : const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
369 : const int old_count = BlockCount(slot_index);
370 179500 : set(slot_start + kSlotBlockCountIndex, Smi::FromInt(old_count + 1));
371 179500 : }
372 :
373 46264 : void CoverageInfo::ResetBlockCount(int slot_index) {
374 : DCHECK_LT(slot_index, SlotCount());
375 : const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
376 46264 : set(slot_start + kSlotBlockCountIndex, Smi::kZero);
377 46264 : }
378 :
379 0 : void CoverageInfo::Print(std::unique_ptr<char[]> function_name) {
380 : DCHECK(FLAG_trace_block_coverage);
381 : DisallowHeapAllocation no_gc;
382 :
383 0 : StdoutStream os;
384 0 : os << "Coverage info (";
385 0 : if (strlen(function_name.get()) > 0) {
386 0 : os << function_name.get();
387 : } else {
388 0 : os << "{anonymous}";
389 : }
390 : os << "):" << std::endl;
391 :
392 0 : for (int i = 0; i < SlotCount(); i++) {
393 0 : os << "{" << StartSourcePosition(i) << "," << EndSourcePosition(i) << "}"
394 : << std::endl;
395 : }
396 0 : }
397 :
398 : } // namespace internal
399 121996 : } // namespace v8
|