V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
instrument-arm64.cc
1 // Copyright 2013 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/arm64/instrument-arm64.h"
6 
7 namespace v8 {
8 namespace internal {
9 
10 Counter::Counter(const char* name, CounterType type)
11  : count_(0), enabled_(false), type_(type) {
12  DCHECK_NOT_NULL(name);
13  strncpy(name_, name, kCounterNameMaxLength);
14 }
15 
16 
17 void Counter::Enable() {
18  enabled_ = true;
19 }
20 
21 
22 void Counter::Disable() {
23  enabled_ = false;
24 }
25 
26 
27 bool Counter::IsEnabled() {
28  return enabled_;
29 }
30 
31 
32 void Counter::Increment() {
33  if (enabled_) {
34  count_++;
35  }
36 }
37 
38 
39 uint64_t Counter::count() {
40  uint64_t result = count_;
41  if (type_ == Gauge) {
42  // If the counter is a Gauge, reset the count after reading.
43  count_ = 0;
44  }
45  return result;
46 }
47 
48 
49 const char* Counter::name() {
50  return name_;
51 }
52 
53 
54 CounterType Counter::type() {
55  return type_;
56 }
57 
58 
59 typedef struct {
60  const char* name;
61  CounterType type;
63 
64 static const CounterDescriptor kCounterList[] = {
65  {"Instruction", Cumulative},
66 
67  {"Move Immediate", Gauge},
68  {"Add/Sub DP", Gauge},
69  {"Logical DP", Gauge},
70  {"Other Int DP", Gauge},
71  {"FP DP", Gauge},
72  {"NEON", Gauge},
73 
74  {"Conditional Select", Gauge},
75  {"Conditional Compare", Gauge},
76 
77  {"Unconditional Branch", Gauge},
78  {"Compare and Branch", Gauge},
79  {"Test and Branch", Gauge},
80  {"Conditional Branch", Gauge},
81 
82  {"Load Integer", Gauge},
83  {"Load FP", Gauge},
84  {"Load Pair", Gauge},
85  {"Load Literal", Gauge},
86  {"Load Acquire", Gauge},
87 
88  {"Store Integer", Gauge},
89  {"Store FP", Gauge},
90  {"Store Pair", Gauge},
91  {"Store Release", Gauge},
92 
93  {"PC Addressing", Gauge},
94  {"Other", Gauge},
95 };
96 
97 Instrument::Instrument(const char* datafile, uint64_t sample_period)
98  : output_stream_(stderr), sample_period_(sample_period) {
99  // Set up the output stream. If datafile is non-nullptr, use that file. If it
100  // can't be opened, or datafile is nullptr, use stderr.
101  if (datafile != nullptr) {
102  output_stream_ = fopen(datafile, "w");
103  if (output_stream_ == nullptr) {
104  fprintf(stderr, "Can't open output file %s. Using stderr.\n", datafile);
105  output_stream_ = stderr;
106  }
107  }
108 
109  static const int num_counters = arraysize(kCounterList);
110 
111  // Dump an instrumentation description comment at the top of the file.
112  fprintf(output_stream_, "# counters=%d\n", num_counters);
113  fprintf(output_stream_, "# sample_period=%" PRIu64 "\n", sample_period_);
114 
115  // Construct Counter objects from counter description array.
116  for (int i = 0; i < num_counters; i++) {
117  Counter* counter = new Counter(kCounterList[i].name, kCounterList[i].type);
118  counters_.push_back(counter);
119  }
120 
121  DumpCounterNames();
122 }
123 
124 
125 Instrument::~Instrument() {
126  // Dump any remaining instruction data to the output file.
127  DumpCounters();
128 
129  // Free all the counter objects.
130  std::list<Counter*>::iterator it;
131  for (it = counters_.begin(); it != counters_.end(); it++) {
132  delete *it;
133  }
134 
135  if (output_stream_ != stderr) {
136  fclose(output_stream_);
137  }
138 }
139 
140 
141 void Instrument::Update() {
142  // Increment the instruction counter, and dump all counters if a sample period
143  // has elapsed.
144  static Counter* counter = GetCounter("Instruction");
145  DCHECK(counter->type() == Cumulative);
146  counter->Increment();
147 
148  if (counter->IsEnabled() && (counter->count() % sample_period_) == 0) {
149  DumpCounters();
150  }
151 }
152 
153 
154 void Instrument::DumpCounters() {
155  // Iterate through the counter objects, dumping their values to the output
156  // stream.
157  std::list<Counter*>::const_iterator it;
158  for (it = counters_.begin(); it != counters_.end(); it++) {
159  fprintf(output_stream_, "%" PRIu64 ",", (*it)->count());
160  }
161  fprintf(output_stream_, "\n");
162  fflush(output_stream_);
163 }
164 
165 
166 void Instrument::DumpCounterNames() {
167  // Iterate through the counter objects, dumping the counter names to the
168  // output stream.
169  std::list<Counter*>::const_iterator it;
170  for (it = counters_.begin(); it != counters_.end(); it++) {
171  fprintf(output_stream_, "%s,", (*it)->name());
172  }
173  fprintf(output_stream_, "\n");
174  fflush(output_stream_);
175 }
176 
177 
178 void Instrument::HandleInstrumentationEvent(unsigned event) {
179  switch (event) {
180  case InstrumentStateEnable: Enable(); break;
181  case InstrumentStateDisable: Disable(); break;
182  default: DumpEventMarker(event);
183  }
184 }
185 
186 
187 void Instrument::DumpEventMarker(unsigned marker) {
188  // Dumpan event marker to the output stream as a specially formatted comment
189  // line.
190  static Counter* counter = GetCounter("Instruction");
191 
192  fprintf(output_stream_, "# %c%c @ %" PRId64 "\n", marker & 0xFF,
193  (marker >> 8) & 0xFF, counter->count());
194 }
195 
196 
197 Counter* Instrument::GetCounter(const char* name) {
198  // Get a Counter object by name from the counter list.
199  std::list<Counter*>::const_iterator it;
200  for (it = counters_.begin(); it != counters_.end(); it++) {
201  if (strcmp((*it)->name(), name) == 0) {
202  return *it;
203  }
204  }
205 
206  // A Counter by that name does not exist: print an error message to stderr
207  // and the output file, and exit.
208  static const char* error_message =
209  "# Error: Unknown counter \"%s\". Exiting.\n";
210  fprintf(stderr, error_message, name);
211  fprintf(output_stream_, error_message, name);
212  exit(1);
213 }
214 
215 
216 void Instrument::Enable() {
217  std::list<Counter*>::iterator it;
218  for (it = counters_.begin(); it != counters_.end(); it++) {
219  (*it)->Enable();
220  }
221 }
222 
223 
224 void Instrument::Disable() {
225  std::list<Counter*>::iterator it;
226  for (it = counters_.begin(); it != counters_.end(); it++) {
227  (*it)->Disable();
228  }
229 }
230 
231 
232 void Instrument::VisitPCRelAddressing(Instruction* instr) {
233  Update();
234  static Counter* counter = GetCounter("PC Addressing");
235  counter->Increment();
236 }
237 
238 
239 void Instrument::VisitAddSubImmediate(Instruction* instr) {
240  Update();
241  static Counter* counter = GetCounter("Add/Sub DP");
242  counter->Increment();
243 }
244 
245 
246 void Instrument::VisitLogicalImmediate(Instruction* instr) {
247  Update();
248  static Counter* counter = GetCounter("Logical DP");
249  counter->Increment();
250 }
251 
252 
253 void Instrument::VisitMoveWideImmediate(Instruction* instr) {
254  Update();
255  static Counter* counter = GetCounter("Move Immediate");
256 
257  if (instr->IsMovn() && (instr->Rd() == kZeroRegCode)) {
258  unsigned imm = instr->ImmMoveWide();
259  HandleInstrumentationEvent(imm);
260  } else {
261  counter->Increment();
262  }
263 }
264 
265 
266 void Instrument::VisitBitfield(Instruction* instr) {
267  Update();
268  static Counter* counter = GetCounter("Other Int DP");
269  counter->Increment();
270 }
271 
272 
273 void Instrument::VisitExtract(Instruction* instr) {
274  Update();
275  static Counter* counter = GetCounter("Other Int DP");
276  counter->Increment();
277 }
278 
279 
280 void Instrument::VisitUnconditionalBranch(Instruction* instr) {
281  Update();
282  static Counter* counter = GetCounter("Unconditional Branch");
283  counter->Increment();
284 }
285 
286 
287 void Instrument::VisitUnconditionalBranchToRegister(Instruction* instr) {
288  Update();
289  static Counter* counter = GetCounter("Unconditional Branch");
290  counter->Increment();
291 }
292 
293 
294 void Instrument::VisitCompareBranch(Instruction* instr) {
295  Update();
296  static Counter* counter = GetCounter("Compare and Branch");
297  counter->Increment();
298 }
299 
300 
301 void Instrument::VisitTestBranch(Instruction* instr) {
302  Update();
303  static Counter* counter = GetCounter("Test and Branch");
304  counter->Increment();
305 }
306 
307 
308 void Instrument::VisitConditionalBranch(Instruction* instr) {
309  Update();
310  static Counter* counter = GetCounter("Conditional Branch");
311  counter->Increment();
312 }
313 
314 
315 void Instrument::VisitSystem(Instruction* instr) {
316  Update();
317  static Counter* counter = GetCounter("Other");
318  counter->Increment();
319 }
320 
321 
322 void Instrument::VisitException(Instruction* instr) {
323  Update();
324  static Counter* counter = GetCounter("Other");
325  counter->Increment();
326 }
327 
328 
329 void Instrument::InstrumentLoadStorePair(Instruction* instr) {
330  static Counter* load_pair_counter = GetCounter("Load Pair");
331  static Counter* store_pair_counter = GetCounter("Store Pair");
332  if (instr->Mask(LoadStorePairLBit) != 0) {
333  load_pair_counter->Increment();
334  } else {
335  store_pair_counter->Increment();
336  }
337 }
338 
339 
340 void Instrument::VisitLoadStorePairPostIndex(Instruction* instr) {
341  Update();
342  InstrumentLoadStorePair(instr);
343 }
344 
345 
346 void Instrument::VisitLoadStorePairOffset(Instruction* instr) {
347  Update();
348  InstrumentLoadStorePair(instr);
349 }
350 
351 
352 void Instrument::VisitLoadStorePairPreIndex(Instruction* instr) {
353  Update();
354  InstrumentLoadStorePair(instr);
355 }
356 
357 
358 void Instrument::VisitLoadLiteral(Instruction* instr) {
359  Update();
360  static Counter* counter = GetCounter("Load Literal");
361  counter->Increment();
362 }
363 
364 
365 void Instrument::InstrumentLoadStore(Instruction* instr) {
366  static Counter* load_int_counter = GetCounter("Load Integer");
367  static Counter* store_int_counter = GetCounter("Store Integer");
368  static Counter* load_fp_counter = GetCounter("Load FP");
369  static Counter* store_fp_counter = GetCounter("Store FP");
370 
371  switch (instr->Mask(LoadStoreMask)) {
372  case STRB_w: // Fall through.
373  case STRH_w: // Fall through.
374  case STR_w: // Fall through.
375  case STR_x: store_int_counter->Increment(); break;
376  case STR_s: // Fall through.
377  case STR_d: store_fp_counter->Increment(); break;
378  case LDRB_w: // Fall through.
379  case LDRH_w: // Fall through.
380  case LDR_w: // Fall through.
381  case LDR_x: // Fall through.
382  case LDRSB_x: // Fall through.
383  case LDRSH_x: // Fall through.
384  case LDRSW_x: // Fall through.
385  case LDRSB_w: // Fall through.
386  case LDRSH_w: load_int_counter->Increment(); break;
387  case LDR_s: // Fall through.
388  case LDR_d: load_fp_counter->Increment(); break;
389  default: UNREACHABLE();
390  }
391 }
392 
393 
394 void Instrument::VisitLoadStoreUnscaledOffset(Instruction* instr) {
395  Update();
396  InstrumentLoadStore(instr);
397 }
398 
399 
400 void Instrument::VisitLoadStorePostIndex(Instruction* instr) {
401  Update();
402  InstrumentLoadStore(instr);
403 }
404 
405 
406 void Instrument::VisitLoadStorePreIndex(Instruction* instr) {
407  Update();
408  InstrumentLoadStore(instr);
409 }
410 
411 
412 void Instrument::VisitLoadStoreRegisterOffset(Instruction* instr) {
413  Update();
414  InstrumentLoadStore(instr);
415 }
416 
417 
418 void Instrument::VisitLoadStoreUnsignedOffset(Instruction* instr) {
419  Update();
420  InstrumentLoadStore(instr);
421 }
422 
423 void Instrument::VisitLoadStoreAcquireRelease(Instruction* instr) {
424  Update();
425  static Counter* load_counter = GetCounter("Load Acquire");
426  static Counter* store_counter = GetCounter("Store Release");
427 
428  switch (instr->Mask(LoadStoreAcquireReleaseMask)) {
429  case LDAR_b: // Fall-through.
430  case LDAR_h: // Fall-through.
431  case LDAR_w: // Fall-through.
432  case LDAR_x: // Fall-through.
433  case LDAXR_b: // Fall-through.
434  case LDAXR_h: // Fall-through.
435  case LDAXR_w: // Fall-through.
436  case LDAXR_x: load_counter->Increment(); break;
437  case STLR_b: // Fall-through.
438  case STLR_h: // Fall-through.
439  case STLR_w: // Fall-through.
440  case STLR_x: // Fall-through.
441  case STLXR_b: // Fall-through.
442  case STLXR_h: // Fall-through.
443  case STLXR_w: // Fall-through.
444  case STLXR_x: store_counter->Increment(); break;
445  default: UNREACHABLE();
446  }
447 }
448 
449 void Instrument::VisitLogicalShifted(Instruction* instr) {
450  Update();
451  static Counter* counter = GetCounter("Logical DP");
452  counter->Increment();
453 }
454 
455 
456 void Instrument::VisitAddSubShifted(Instruction* instr) {
457  Update();
458  static Counter* counter = GetCounter("Add/Sub DP");
459  counter->Increment();
460 }
461 
462 
463 void Instrument::VisitAddSubExtended(Instruction* instr) {
464  Update();
465  static Counter* counter = GetCounter("Add/Sub DP");
466  counter->Increment();
467 }
468 
469 
470 void Instrument::VisitAddSubWithCarry(Instruction* instr) {
471  Update();
472  static Counter* counter = GetCounter("Add/Sub DP");
473  counter->Increment();
474 }
475 
476 
477 void Instrument::VisitConditionalCompareRegister(Instruction* instr) {
478  Update();
479  static Counter* counter = GetCounter("Conditional Compare");
480  counter->Increment();
481 }
482 
483 
484 void Instrument::VisitConditionalCompareImmediate(Instruction* instr) {
485  Update();
486  static Counter* counter = GetCounter("Conditional Compare");
487  counter->Increment();
488 }
489 
490 
491 void Instrument::VisitConditionalSelect(Instruction* instr) {
492  Update();
493  static Counter* counter = GetCounter("Conditional Select");
494  counter->Increment();
495 }
496 
497 
498 void Instrument::VisitDataProcessing1Source(Instruction* instr) {
499  Update();
500  static Counter* counter = GetCounter("Other Int DP");
501  counter->Increment();
502 }
503 
504 
505 void Instrument::VisitDataProcessing2Source(Instruction* instr) {
506  Update();
507  static Counter* counter = GetCounter("Other Int DP");
508  counter->Increment();
509 }
510 
511 
512 void Instrument::VisitDataProcessing3Source(Instruction* instr) {
513  Update();
514  static Counter* counter = GetCounter("Other Int DP");
515  counter->Increment();
516 }
517 
518 
519 void Instrument::VisitFPCompare(Instruction* instr) {
520  Update();
521  static Counter* counter = GetCounter("FP DP");
522  counter->Increment();
523 }
524 
525 
526 void Instrument::VisitFPConditionalCompare(Instruction* instr) {
527  Update();
528  static Counter* counter = GetCounter("Conditional Compare");
529  counter->Increment();
530 }
531 
532 
533 void Instrument::VisitFPConditionalSelect(Instruction* instr) {
534  Update();
535  static Counter* counter = GetCounter("Conditional Select");
536  counter->Increment();
537 }
538 
539 
540 void Instrument::VisitFPImmediate(Instruction* instr) {
541  Update();
542  static Counter* counter = GetCounter("FP DP");
543  counter->Increment();
544 }
545 
546 
547 void Instrument::VisitFPDataProcessing1Source(Instruction* instr) {
548  Update();
549  static Counter* counter = GetCounter("FP DP");
550  counter->Increment();
551 }
552 
553 
554 void Instrument::VisitFPDataProcessing2Source(Instruction* instr) {
555  Update();
556  static Counter* counter = GetCounter("FP DP");
557  counter->Increment();
558 }
559 
560 
561 void Instrument::VisitFPDataProcessing3Source(Instruction* instr) {
562  Update();
563  static Counter* counter = GetCounter("FP DP");
564  counter->Increment();
565 }
566 
567 
568 void Instrument::VisitFPIntegerConvert(Instruction* instr) {
569  Update();
570  static Counter* counter = GetCounter("FP DP");
571  counter->Increment();
572 }
573 
574 
575 void Instrument::VisitFPFixedPointConvert(Instruction* instr) {
576  Update();
577  static Counter* counter = GetCounter("FP DP");
578  counter->Increment();
579 }
580 
581 void Instrument::VisitNEON2RegMisc(Instruction* instr) {
582  USE(instr);
583  Update();
584  static Counter* counter = GetCounter("NEON");
585  counter->Increment();
586 }
587 
588 void Instrument::VisitNEON3Different(Instruction* instr) {
589  USE(instr);
590  Update();
591  static Counter* counter = GetCounter("NEON");
592  counter->Increment();
593 }
594 
595 void Instrument::VisitNEON3Same(Instruction* instr) {
596  USE(instr);
597  Update();
598  static Counter* counter = GetCounter("NEON");
599  counter->Increment();
600 }
601 
602 void Instrument::VisitNEONAcrossLanes(Instruction* instr) {
603  USE(instr);
604  Update();
605  static Counter* counter = GetCounter("NEON");
606  counter->Increment();
607 }
608 
609 void Instrument::VisitNEONByIndexedElement(Instruction* instr) {
610  USE(instr);
611  Update();
612  static Counter* counter = GetCounter("NEON");
613  counter->Increment();
614 }
615 
616 void Instrument::VisitNEONCopy(Instruction* instr) {
617  USE(instr);
618  Update();
619  static Counter* counter = GetCounter("NEON");
620  counter->Increment();
621 }
622 
623 void Instrument::VisitNEONExtract(Instruction* instr) {
624  USE(instr);
625  Update();
626  static Counter* counter = GetCounter("NEON");
627  counter->Increment();
628 }
629 
630 void Instrument::VisitNEONLoadStoreMultiStruct(Instruction* instr) {
631  USE(instr);
632  Update();
633  static Counter* counter = GetCounter("NEON");
634  counter->Increment();
635 }
636 
637 void Instrument::VisitNEONLoadStoreMultiStructPostIndex(Instruction* instr) {
638  USE(instr);
639  Update();
640  static Counter* counter = GetCounter("NEON");
641  counter->Increment();
642 }
643 
644 void Instrument::VisitNEONLoadStoreSingleStruct(Instruction* instr) {
645  USE(instr);
646  Update();
647  static Counter* counter = GetCounter("NEON");
648  counter->Increment();
649 }
650 
651 void Instrument::VisitNEONLoadStoreSingleStructPostIndex(Instruction* instr) {
652  USE(instr);
653  Update();
654  static Counter* counter = GetCounter("NEON");
655  counter->Increment();
656 }
657 
658 void Instrument::VisitNEONModifiedImmediate(Instruction* instr) {
659  USE(instr);
660  Update();
661  static Counter* counter = GetCounter("NEON");
662  counter->Increment();
663 }
664 
665 void Instrument::VisitNEONPerm(Instruction* instr) {
666  USE(instr);
667  Update();
668  static Counter* counter = GetCounter("NEON");
669  counter->Increment();
670 }
671 
672 void Instrument::VisitNEONScalar2RegMisc(Instruction* instr) {
673  USE(instr);
674  Update();
675  static Counter* counter = GetCounter("NEON");
676  counter->Increment();
677 }
678 
679 void Instrument::VisitNEONScalar3Diff(Instruction* instr) {
680  USE(instr);
681  Update();
682  static Counter* counter = GetCounter("NEON");
683  counter->Increment();
684 }
685 
686 void Instrument::VisitNEONScalar3Same(Instruction* instr) {
687  USE(instr);
688  Update();
689  static Counter* counter = GetCounter("NEON");
690  counter->Increment();
691 }
692 
693 void Instrument::VisitNEONScalarByIndexedElement(Instruction* instr) {
694  USE(instr);
695  Update();
696  static Counter* counter = GetCounter("NEON");
697  counter->Increment();
698 }
699 
700 void Instrument::VisitNEONScalarCopy(Instruction* instr) {
701  USE(instr);
702  Update();
703  static Counter* counter = GetCounter("NEON");
704  counter->Increment();
705 }
706 
707 void Instrument::VisitNEONScalarPairwise(Instruction* instr) {
708  USE(instr);
709  Update();
710  static Counter* counter = GetCounter("NEON");
711  counter->Increment();
712 }
713 
714 void Instrument::VisitNEONScalarShiftImmediate(Instruction* instr) {
715  USE(instr);
716  Update();
717  static Counter* counter = GetCounter("NEON");
718  counter->Increment();
719 }
720 
721 void Instrument::VisitNEONShiftImmediate(Instruction* instr) {
722  USE(instr);
723  Update();
724  static Counter* counter = GetCounter("NEON");
725  counter->Increment();
726 }
727 
728 void Instrument::VisitNEONTable(Instruction* instr) {
729  USE(instr);
730  Update();
731  static Counter* counter = GetCounter("NEON");
732  counter->Increment();
733 }
734 
735 void Instrument::VisitUnallocated(Instruction* instr) {
736  Update();
737  static Counter* counter = GetCounter("Other");
738  counter->Increment();
739 }
740 
741 
742 void Instrument::VisitUnimplemented(Instruction* instr) {
743  Update();
744  static Counter* counter = GetCounter("Other");
745  counter->Increment();
746 }
747 
748 
749 } // namespace internal
750 } // namespace v8
Definition: libplatform.h:13