V8 Project
instrument-arm64.cc
Go to the documentation of this file.
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 
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(name != NULL);
13  strncpy(name_, name, kCounterNameMaxLength);
14 }
15 
16 
18  enabled_ = true;
19 }
20 
21 
23  enabled_ = false;
24 }
25 
26 
28  return enabled_;
29 }
30 
31 
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 
55  return type_;
56 }
57 
58 
59 typedef struct {
60  const char* name;
63 
64 
65 static const CounterDescriptor kCounterList[] = {
66  {"Instruction", Cumulative},
67 
68  {"Move Immediate", Gauge},
69  {"Add/Sub DP", Gauge},
70  {"Logical DP", Gauge},
71  {"Other Int DP", Gauge},
72  {"FP DP", 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 
87  {"Store Integer", Gauge},
88  {"Store FP", Gauge},
89  {"Store Pair", Gauge},
90 
91  {"PC Addressing", Gauge},
92  {"Other", Gauge},
93  {"SP Adjust", Gauge},
94 };
95 
96 
97 Instrument::Instrument(const char* datafile, uint64_t sample_period)
98  : output_stream_(stderr), sample_period_(sample_period) {
99 
100  // Set up the output stream. If datafile is non-NULL, use that file. If it
101  // can't be opened, or datafile is NULL, use stderr.
102  if (datafile != NULL) {
103  output_stream_ = fopen(datafile, "w");
104  if (output_stream_ == NULL) {
105  fprintf(stderr, "Can't open output file %s. Using stderr.\n", datafile);
106  output_stream_ = stderr;
107  }
108  }
109 
110  static const int num_counters = arraysize(kCounterList);
111 
112  // Dump an instrumentation description comment at the top of the file.
113  fprintf(output_stream_, "# counters=%d\n", num_counters);
114  fprintf(output_stream_, "# sample_period=%" PRIu64 "\n", sample_period_);
115 
116  // Construct Counter objects from counter description array.
117  for (int i = 0; i < num_counters; i++) {
118  Counter* counter = new Counter(kCounterList[i].name, kCounterList[i].type);
119  counters_.push_back(counter);
120  }
121 
123 }
124 
125 
127  // Dump any remaining instruction data to the output file.
128  DumpCounters();
129 
130  // Free all the counter objects.
131  std::list<Counter*>::iterator it;
132  for (it = counters_.begin(); it != counters_.end(); it++) {
133  delete *it;
134  }
135 
136  if (output_stream_ != stderr) {
137  fclose(output_stream_);
138  }
139 }
140 
141 
143  // Increment the instruction counter, and dump all counters if a sample period
144  // has elapsed.
145  static Counter* counter = GetCounter("Instruction");
146  DCHECK(counter->type() == Cumulative);
147  counter->Increment();
148 
149  if (counter->IsEnabled() && (counter->count() % sample_period_) == 0) {
150  DumpCounters();
151  }
152 }
153 
154 
156  // Iterate through the counter objects, dumping their values to the output
157  // stream.
158  std::list<Counter*>::const_iterator it;
159  for (it = counters_.begin(); it != counters_.end(); it++) {
160  fprintf(output_stream_, "%" PRIu64 ",", (*it)->count());
161  }
162  fprintf(output_stream_, "\n");
163  fflush(output_stream_);
164 }
165 
166 
168  // Iterate through the counter objects, dumping the counter names to the
169  // output stream.
170  std::list<Counter*>::const_iterator it;
171  for (it = counters_.begin(); it != counters_.end(); it++) {
172  fprintf(output_stream_, "%s,", (*it)->name());
173  }
174  fprintf(output_stream_, "\n");
175  fflush(output_stream_);
176 }
177 
178 
180  switch (event) {
181  case InstrumentStateEnable: Enable(); break;
182  case InstrumentStateDisable: Disable(); break;
183  default: DumpEventMarker(event);
184  }
185 }
186 
187 
188 void Instrument::DumpEventMarker(unsigned marker) {
189  // Dumpan event marker to the output stream as a specially formatted comment
190  // line.
191  static Counter* counter = GetCounter("Instruction");
192 
193  fprintf(output_stream_, "# %c%c @ %" PRId64 "\n", marker & 0xff,
194  (marker >> 8) & 0xff, counter->count());
195 }
196 
197 
199  // Get a Counter object by name from the counter list.
200  std::list<Counter*>::const_iterator it;
201  for (it = counters_.begin(); it != counters_.end(); it++) {
202  if (strcmp((*it)->name(), name) == 0) {
203  return *it;
204  }
205  }
206 
207  // A Counter by that name does not exist: print an error message to stderr
208  // and the output file, and exit.
209  static const char* error_message =
210  "# Error: Unknown counter \"%s\". Exiting.\n";
211  fprintf(stderr, error_message, name);
212  fprintf(output_stream_, error_message, name);
213  exit(1);
214 }
215 
216 
218  std::list<Counter*>::iterator it;
219  for (it = counters_.begin(); it != counters_.end(); it++) {
220  (*it)->Enable();
221  }
222 }
223 
224 
226  std::list<Counter*>::iterator it;
227  for (it = counters_.begin(); it != counters_.end(); it++) {
228  (*it)->Disable();
229  }
230 }
231 
232 
233 void Instrument::VisitPCRelAddressing(Instruction* instr) {
234  Update();
235  static Counter* counter = GetCounter("PC Addressing");
236  counter->Increment();
237 }
238 
239 
240 void Instrument::VisitAddSubImmediate(Instruction* instr) {
241  Update();
242  static Counter* sp_counter = GetCounter("SP Adjust");
243  static Counter* add_sub_counter = GetCounter("Add/Sub DP");
244  if (((instr->Mask(AddSubOpMask) == SUB) ||
245  (instr->Mask(AddSubOpMask) == ADD)) &&
246  (instr->Rd() == 31) && (instr->Rn() == 31)) {
247  // Count adjustments to the C stack pointer caused by V8 needing two SPs.
248  sp_counter->Increment();
249  } else {
250  add_sub_counter->Increment();
251  }
252 }
253 
254 
255 void Instrument::VisitLogicalImmediate(Instruction* instr) {
256  Update();
257  static Counter* counter = GetCounter("Logical DP");
258  counter->Increment();
259 }
260 
261 
262 void Instrument::VisitMoveWideImmediate(Instruction* instr) {
263  Update();
264  static Counter* counter = GetCounter("Move Immediate");
265 
266  if (instr->IsMovn() && (instr->Rd() == kZeroRegCode)) {
267  unsigned imm = instr->ImmMoveWide();
269  } else {
270  counter->Increment();
271  }
272 }
273 
274 
275 void Instrument::VisitBitfield(Instruction* instr) {
276  Update();
277  static Counter* counter = GetCounter("Other Int DP");
278  counter->Increment();
279 }
280 
281 
282 void Instrument::VisitExtract(Instruction* instr) {
283  Update();
284  static Counter* counter = GetCounter("Other Int DP");
285  counter->Increment();
286 }
287 
288 
289 void Instrument::VisitUnconditionalBranch(Instruction* instr) {
290  Update();
291  static Counter* counter = GetCounter("Unconditional Branch");
292  counter->Increment();
293 }
294 
295 
296 void Instrument::VisitUnconditionalBranchToRegister(Instruction* instr) {
297  Update();
298  static Counter* counter = GetCounter("Unconditional Branch");
299  counter->Increment();
300 }
301 
302 
303 void Instrument::VisitCompareBranch(Instruction* instr) {
304  Update();
305  static Counter* counter = GetCounter("Compare and Branch");
306  counter->Increment();
307 }
308 
309 
310 void Instrument::VisitTestBranch(Instruction* instr) {
311  Update();
312  static Counter* counter = GetCounter("Test and Branch");
313  counter->Increment();
314 }
315 
316 
317 void Instrument::VisitConditionalBranch(Instruction* instr) {
318  Update();
319  static Counter* counter = GetCounter("Conditional Branch");
320  counter->Increment();
321 }
322 
323 
324 void Instrument::VisitSystem(Instruction* instr) {
325  Update();
326  static Counter* counter = GetCounter("Other");
327  counter->Increment();
328 }
329 
330 
331 void Instrument::VisitException(Instruction* instr) {
332  Update();
333  static Counter* counter = GetCounter("Other");
334  counter->Increment();
335 }
336 
337 
339  static Counter* load_pair_counter = GetCounter("Load Pair");
340  static Counter* store_pair_counter = GetCounter("Store Pair");
341  if (instr->Mask(LoadStorePairLBit) != 0) {
342  load_pair_counter->Increment();
343  } else {
344  store_pair_counter->Increment();
345  }
346 }
347 
348 
349 void Instrument::VisitLoadStorePairPostIndex(Instruction* instr) {
350  Update();
352 }
353 
354 
355 void Instrument::VisitLoadStorePairOffset(Instruction* instr) {
356  Update();
358 }
359 
360 
361 void Instrument::VisitLoadStorePairPreIndex(Instruction* instr) {
362  Update();
364 }
365 
366 
367 void Instrument::VisitLoadStorePairNonTemporal(Instruction* instr) {
368  Update();
370 }
371 
372 
373 void Instrument::VisitLoadLiteral(Instruction* instr) {
374  Update();
375  static Counter* counter = GetCounter("Load Literal");
376  counter->Increment();
377 }
378 
379 
381  static Counter* load_int_counter = GetCounter("Load Integer");
382  static Counter* store_int_counter = GetCounter("Store Integer");
383  static Counter* load_fp_counter = GetCounter("Load FP");
384  static Counter* store_fp_counter = GetCounter("Store FP");
385 
386  switch (instr->Mask(LoadStoreOpMask)) {
387  case STRB_w: // Fall through.
388  case STRH_w: // Fall through.
389  case STR_w: // Fall through.
390  case STR_x: store_int_counter->Increment(); break;
391  case STR_s: // Fall through.
392  case STR_d: store_fp_counter->Increment(); break;
393  case LDRB_w: // Fall through.
394  case LDRH_w: // Fall through.
395  case LDR_w: // Fall through.
396  case LDR_x: // Fall through.
397  case LDRSB_x: // Fall through.
398  case LDRSH_x: // Fall through.
399  case LDRSW_x: // Fall through.
400  case LDRSB_w: // Fall through.
401  case LDRSH_w: load_int_counter->Increment(); break;
402  case LDR_s: // Fall through.
403  case LDR_d: load_fp_counter->Increment(); break;
404  default: UNREACHABLE();
405  }
406 }
407 
408 
409 void Instrument::VisitLoadStoreUnscaledOffset(Instruction* instr) {
410  Update();
411  InstrumentLoadStore(instr);
412 }
413 
414 
415 void Instrument::VisitLoadStorePostIndex(Instruction* instr) {
416  Update();
417  InstrumentLoadStore(instr);
418 }
419 
420 
421 void Instrument::VisitLoadStorePreIndex(Instruction* instr) {
422  Update();
423  InstrumentLoadStore(instr);
424 }
425 
426 
427 void Instrument::VisitLoadStoreRegisterOffset(Instruction* instr) {
428  Update();
429  InstrumentLoadStore(instr);
430 }
431 
432 
433 void Instrument::VisitLoadStoreUnsignedOffset(Instruction* instr) {
434  Update();
435  InstrumentLoadStore(instr);
436 }
437 
438 
439 void Instrument::VisitLogicalShifted(Instruction* instr) {
440  Update();
441  static Counter* counter = GetCounter("Logical DP");
442  counter->Increment();
443 }
444 
445 
446 void Instrument::VisitAddSubShifted(Instruction* instr) {
447  Update();
448  static Counter* counter = GetCounter("Add/Sub DP");
449  counter->Increment();
450 }
451 
452 
453 void Instrument::VisitAddSubExtended(Instruction* instr) {
454  Update();
455  static Counter* sp_counter = GetCounter("SP Adjust");
456  static Counter* add_sub_counter = GetCounter("Add/Sub DP");
457  if (((instr->Mask(AddSubOpMask) == SUB) ||
458  (instr->Mask(AddSubOpMask) == ADD)) &&
459  (instr->Rd() == 31) && (instr->Rn() == 31)) {
460  // Count adjustments to the C stack pointer caused by V8 needing two SPs.
461  sp_counter->Increment();
462  } else {
463  add_sub_counter->Increment();
464  }
465 }
466 
467 
468 void Instrument::VisitAddSubWithCarry(Instruction* instr) {
469  Update();
470  static Counter* counter = GetCounter("Add/Sub DP");
471  counter->Increment();
472 }
473 
474 
475 void Instrument::VisitConditionalCompareRegister(Instruction* instr) {
476  Update();
477  static Counter* counter = GetCounter("Conditional Compare");
478  counter->Increment();
479 }
480 
481 
482 void Instrument::VisitConditionalCompareImmediate(Instruction* instr) {
483  Update();
484  static Counter* counter = GetCounter("Conditional Compare");
485  counter->Increment();
486 }
487 
488 
489 void Instrument::VisitConditionalSelect(Instruction* instr) {
490  Update();
491  static Counter* counter = GetCounter("Conditional Select");
492  counter->Increment();
493 }
494 
495 
496 void Instrument::VisitDataProcessing1Source(Instruction* instr) {
497  Update();
498  static Counter* counter = GetCounter("Other Int DP");
499  counter->Increment();
500 }
501 
502 
503 void Instrument::VisitDataProcessing2Source(Instruction* instr) {
504  Update();
505  static Counter* counter = GetCounter("Other Int DP");
506  counter->Increment();
507 }
508 
509 
510 void Instrument::VisitDataProcessing3Source(Instruction* instr) {
511  Update();
512  static Counter* counter = GetCounter("Other Int DP");
513  counter->Increment();
514 }
515 
516 
517 void Instrument::VisitFPCompare(Instruction* instr) {
518  Update();
519  static Counter* counter = GetCounter("FP DP");
520  counter->Increment();
521 }
522 
523 
524 void Instrument::VisitFPConditionalCompare(Instruction* instr) {
525  Update();
526  static Counter* counter = GetCounter("Conditional Compare");
527  counter->Increment();
528 }
529 
530 
531 void Instrument::VisitFPConditionalSelect(Instruction* instr) {
532  Update();
533  static Counter* counter = GetCounter("Conditional Select");
534  counter->Increment();
535 }
536 
537 
538 void Instrument::VisitFPImmediate(Instruction* instr) {
539  Update();
540  static Counter* counter = GetCounter("FP DP");
541  counter->Increment();
542 }
543 
544 
545 void Instrument::VisitFPDataProcessing1Source(Instruction* instr) {
546  Update();
547  static Counter* counter = GetCounter("FP DP");
548  counter->Increment();
549 }
550 
551 
552 void Instrument::VisitFPDataProcessing2Source(Instruction* instr) {
553  Update();
554  static Counter* counter = GetCounter("FP DP");
555  counter->Increment();
556 }
557 
558 
559 void Instrument::VisitFPDataProcessing3Source(Instruction* instr) {
560  Update();
561  static Counter* counter = GetCounter("FP DP");
562  counter->Increment();
563 }
564 
565 
566 void Instrument::VisitFPIntegerConvert(Instruction* instr) {
567  Update();
568  static Counter* counter = GetCounter("FP DP");
569  counter->Increment();
570 }
571 
572 
573 void Instrument::VisitFPFixedPointConvert(Instruction* instr) {
574  Update();
575  static Counter* counter = GetCounter("FP DP");
576  counter->Increment();
577 }
578 
579 
580 void Instrument::VisitUnallocated(Instruction* instr) {
581  Update();
582  static Counter* counter = GetCounter("Other");
583  counter->Increment();
584 }
585 
586 
587 void Instrument::VisitUnimplemented(Instruction* instr) {
588  Update();
589  static Counter* counter = GetCounter("Other");
590  counter->Increment();
591 }
592 
593 
594 } } // namespace v8::internal
Definition: d8.h:23
char name_[kCounterNameMaxLength]
Counter(const char *name, CounterType type=Gauge)
Instr Mask(uint32_t mask) const
void HandleInstrumentationEvent(unsigned event)
void DumpEventMarker(unsigned marker)
std::list< Counter * > counters_
Counter * GetCounter(const char *name)
Instrument(const char *datafile=NULL, uint64_t sample_period=kDefaultInstrumentationSamplingPeriod)
void InstrumentLoadStore(Instruction *instr)
void InstrumentLoadStorePair(Instruction *instr)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
#define arraysize(array)
Definition: macros.h:86
static const CounterDescriptor kCounterList[]
const int kCounterNameMaxLength
const unsigned kZeroRegCode
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20