v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
allocation-tracker.cc
Go to the documentation of this file.
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "allocation-tracker.h"
31 
33 #include "frames-inl.h"
34 
35 namespace v8 {
36 namespace internal {
37 
39  AllocationTraceTree* tree, unsigned function_info_index)
40  : tree_(tree),
41  function_info_index_(function_info_index),
42  total_size_(0),
43  allocation_count_(0),
44  id_(tree->next_node_id()) {
45 }
46 
47 
49  for (int i = 0; i < children_.length(); i++) delete children_[i];
50 }
51 
52 
54  unsigned function_info_index) {
55  for (int i = 0; i < children_.length(); i++) {
56  AllocationTraceNode* node = children_[i];
57  if (node->function_info_index() == function_info_index) return node;
58  }
59  return NULL;
60 }
61 
62 
64  unsigned function_info_index) {
65  AllocationTraceNode* child = FindChild(function_info_index);
66  if (child == NULL) {
67  child = new AllocationTraceNode(tree_, function_info_index);
68  children_.Add(child);
69  }
70  return child;
71 }
72 
73 
75  total_size_ += size;
76  ++allocation_count_;
77 }
78 
79 
80 void AllocationTraceNode::Print(int indent, AllocationTracker* tracker) {
81  OS::Print("%10u %10u %*c", total_size_, allocation_count_, indent, ' ');
82  if (tracker != NULL) {
84  tracker->function_info_list()[function_info_index_];
85  OS::Print("%s #%u", info->name, id_);
86  } else {
87  OS::Print("%u #%u", function_info_index_, id_);
88  }
89  OS::Print("\n");
90  indent += 2;
91  for (int i = 0; i < children_.length(); i++) {
92  children_[i]->Print(indent, tracker);
93  }
94 }
95 
96 
98  : next_node_id_(1),
99  root_(this, 0) {
100 }
101 
102 
104 }
105 
106 
108  const Vector<unsigned>& path) {
109  AllocationTraceNode* node = root();
110  for (unsigned* entry = path.start() + path.length() - 1;
111  entry != path.start() - 1;
112  --entry) {
113  node = node->FindOrAddChild(*entry);
114  }
115  return node;
116 }
117 
118 
120  OS::Print("[AllocationTraceTree:]\n");
121  OS::Print("Total size | Allocation count | Function id | id\n");
122  root()->Print(0, tracker);
123 }
124 
125 
126 void AllocationTracker::DeleteUnresolvedLocation(
127  UnresolvedLocation** location) {
128  delete *location;
129 }
130 
131 
133  : name(""),
134  function_id(0),
135  script_name(""),
136  script_id(0),
137  line(-1),
138  column(-1) {
139 }
140 
141 
143  unsigned trace_node_id) {
144  Address end = start + size;
145  RemoveRange(start, end);
146 
147  RangeStack new_range(start, trace_node_id);
148  ranges_.insert(RangeMap::value_type(end, new_range));
149 }
150 
151 
153  RangeMap::const_iterator it = ranges_.upper_bound(addr);
154  if (it == ranges_.end()) return 0;
155  if (it->second.start <= addr) {
156  return it->second.trace_node_id;
157  }
158  return 0;
159 }
160 
161 
163  unsigned trace_node_id = GetTraceNodeId(from);
164  if (trace_node_id == 0) return;
165  RemoveRange(from, from + size);
166  AddRange(to, size, trace_node_id);
167 }
168 
169 
171  ranges_.clear();
172 }
173 
174 
176  PrintF("[AddressToTraceMap (%" V8PRIuPTR "): \n", ranges_.size());
177  for (RangeMap::iterator it = ranges_.begin(); it != ranges_.end(); ++it) {
178  PrintF("[%p - %p] => %u\n", it->second.start, it->first,
179  it->second.trace_node_id);
180  }
181  PrintF("]\n");
182 }
183 
184 
185 void AddressToTraceMap::RemoveRange(Address start, Address end) {
186  RangeMap::iterator it = ranges_.upper_bound(start);
187  if (it == ranges_.end()) return;
188 
189  RangeStack prev_range(0, 0);
190 
191  RangeMap::iterator to_remove_begin = it;
192  if (it->second.start < start) {
193  prev_range = it->second;
194  }
195  do {
196  if (it->first > end) {
197  if (it->second.start < end) {
198  it->second.start = end;
199  }
200  break;
201  }
202  ++it;
203  }
204  while (it != ranges_.end());
205 
206  ranges_.erase(to_remove_begin, it);
207 
208  if (prev_range.start != 0) {
209  ranges_.insert(RangeMap::value_type(start, prev_range));
210  }
211 }
212 
213 
214 static bool AddressesMatch(void* key1, void* key2) {
215  return key1 == key2;
216 }
217 
218 
219 void AllocationTracker::DeleteFunctionInfo(FunctionInfo** info) {
220  delete *info;
221 }
222 
223 
225  HeapObjectsMap* ids, StringsStorage* names)
226  : ids_(ids),
227  names_(names),
228  id_to_function_info_index_(AddressesMatch),
229  info_index_for_other_state_(0) {
230  FunctionInfo* info = new FunctionInfo();
231  info->name = "(root)";
232  function_info_list_.Add(info);
233 }
234 
235 
237  unresolved_locations_.Iterate(DeleteUnresolvedLocation);
238  function_info_list_.Iterate(&DeleteFunctionInfo);
239 }
240 
241 
243  List<UnresolvedLocation*> copy(unresolved_locations_.length());
244  copy.AddAll(unresolved_locations_);
245  unresolved_locations_.Clear();
246  for (int i = 0; i < copy.length(); i++) {
247  copy[i]->Resolve();
248  delete copy[i];
249  }
250 }
251 
252 
254  DisallowHeapAllocation no_allocation;
255  Heap* heap = ids_->heap();
256 
257  // Mark the new block as FreeSpace to make sure the heap is iterable
258  // while we are capturing stack trace.
259  FreeListNode::FromAddress(addr)->set_size(heap, size);
260  ASSERT_EQ(HeapObject::FromAddress(addr)->Size(), size);
262 
263  Isolate* isolate = heap->isolate();
264  int length = 0;
265  StackTraceFrameIterator it(isolate);
266  while (!it.done() && length < kMaxAllocationTraceLength) {
267  JavaScriptFrame* frame = it.frame();
268  SharedFunctionInfo* shared = frame->function()->shared();
269  SnapshotObjectId id = ids_->FindOrAddEntry(
270  shared->address(), shared->Size(), false);
271  allocation_trace_buffer_[length++] = AddFunctionInfo(shared, id);
272  it.Advance();
273  }
274  if (length == 0) {
275  unsigned index = functionInfoIndexForVMState(isolate->current_vm_state());
276  if (index != 0) {
277  allocation_trace_buffer_[length++] = index;
278  }
279  }
280  AllocationTraceNode* top_node = trace_tree_.AddPathFromEnd(
281  Vector<unsigned>(allocation_trace_buffer_, length));
282  top_node->AddAllocation(size);
283 
284  address_to_trace_.AddRange(addr, size, top_node->id());
285 }
286 
287 
288 static uint32_t SnapshotObjectIdHash(SnapshotObjectId id) {
289  return ComputeIntegerHash(static_cast<uint32_t>(id),
290  v8::internal::kZeroHashSeed);
291 }
292 
293 
294 unsigned AllocationTracker::AddFunctionInfo(SharedFunctionInfo* shared,
295  SnapshotObjectId id) {
296  HashMap::Entry* entry = id_to_function_info_index_.Lookup(
297  reinterpret_cast<void*>(id), SnapshotObjectIdHash(id), true);
298  if (entry->value == NULL) {
299  FunctionInfo* info = new FunctionInfo();
300  info->name = names_->GetFunctionName(shared->DebugName());
301  info->function_id = id;
302  if (shared->script()->IsScript()) {
303  Script* script = Script::cast(shared->script());
304  if (script->name()->IsName()) {
305  Name* name = Name::cast(script->name());
306  info->script_name = names_->GetName(name);
307  }
308  info->script_id = script->id()->value();
309  // Converting start offset into line and column may cause heap
310  // allocations so we postpone them until snapshot serialization.
311  unresolved_locations_.Add(new UnresolvedLocation(
312  script,
313  shared->start_position(),
314  info));
315  }
316  entry->value = reinterpret_cast<void*>(function_info_list_.length());
317  function_info_list_.Add(info);
318  }
319  return static_cast<unsigned>(reinterpret_cast<intptr_t>((entry->value)));
320 }
321 
322 
323 unsigned AllocationTracker::functionInfoIndexForVMState(StateTag state) {
324  if (state != OTHER) return 0;
325  if (info_index_for_other_state_ == 0) {
326  FunctionInfo* info = new FunctionInfo();
327  info->name = "(V8 API)";
328  info_index_for_other_state_ = function_info_list_.length();
329  function_info_list_.Add(info);
330  }
331  return info_index_for_other_state_;
332 }
333 
334 
335 AllocationTracker::UnresolvedLocation::UnresolvedLocation(
336  Script* script, int start, FunctionInfo* info)
337  : start_position_(start),
338  info_(info) {
339  script_ = Handle<Script>::cast(
340  script->GetIsolate()->global_handles()->Create(script));
341  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
342  this,
343  &HandleWeakScript);
344 }
345 
346 
347 AllocationTracker::UnresolvedLocation::~UnresolvedLocation() {
348  if (!script_.is_null()) {
349  GlobalHandles::Destroy(reinterpret_cast<Object**>(script_.location()));
350  }
351 }
352 
353 
354 void AllocationTracker::UnresolvedLocation::Resolve() {
355  if (script_.is_null()) return;
356  HandleScope scope(script_->GetIsolate());
357  info_->line = GetScriptLineNumber(script_, start_position_);
358  info_->column = GetScriptColumnNumber(script_, start_position_);
359 }
360 
361 
362 void AllocationTracker::UnresolvedLocation::HandleWeakScript(
364  UnresolvedLocation* loc =
365  reinterpret_cast<UnresolvedLocation*>(data.GetParameter());
366  GlobalHandles::Destroy(reinterpret_cast<Object**>(loc->script_.location()));
367  loc->script_ = Handle<Script>::null();
368 }
369 
370 
371 } } // namespace v8::internal
byte * Address
Definition: globals.h:186
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
static void Destroy(Object **location)
void Print(AllocationTracker *tracker)
void set_size(Heap *heap, int size_in_bytes)
Definition: spaces.cc:2008
void PrintF(const char *format,...)
Definition: v8utils.cc:40
Isolate * isolate()
Definition: heap-inl.h:624
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
SnapshotObjectId FindOrAddEntry(Address addr, unsigned int size, bool accessed=true)
AllocationTraceNode * FindChild(unsigned function_info_index)
const char * GetName(Name *name)
#define ASSERT(condition)
Definition: checks.h:329
static Script * cast(Object *obj)
int GetScriptColumnNumber(Handle< Script > script, int code_pos)
Definition: handles.cc:389
void AddRange(Address addr, int size, unsigned node_id)
AllocationTraceNode * AddPathFromEnd(const Vector< unsigned > &path)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
Definition: flags.cc:211
T * start() const
Definition: utils.h:426
const char * GetFunctionName(Name *name)
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
Definition: hashmap.h:131
AllocationTraceNode * FindOrAddChild(unsigned function_info_index)
unsigned GetTraceNodeId(Address addr)
int length() const
Definition: utils.h:420
void AllocationEvent(Address addr, int size)
const List< FunctionInfo * > & function_info_list() const
V8_INLINE P * GetParameter() const
Definition: v8.h:451
static void Print(const char *format,...)
#define V8PRIuPTR
Definition: globals.h:230
int GetScriptLineNumber(Handle< Script > script, int code_pos)
Definition: handles.cc:363
AllocationTracker(HeapObjectsMap *ids, StringsStorage *names)
void MoveObject(Address from, Address to, int size)
uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed)
Definition: utils.h:322
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
uint32_t SnapshotObjectId
Definition: v8-profiler.h:39
static void MakeWeak(Object **location, void *parameter, WeakCallback weak_callback)
static FreeListNode * FromAddress(Address address)
Definition: spaces.h:1504
static Handle< T > null()
Definition: handles.h:80
#define ASSERT_EQ(v1, v2)
Definition: checks.h:330
static HeapObject * FromAddress(Address address)
Definition: objects-inl.h:1369
ContainedInLattice AddRange(ContainedInLattice containment, const int *ranges, int ranges_length, Interval new_range)
Definition: jsregexp.cc:114
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:39
static Name * cast(Object *obj)
void Iterate(void(*callback)(T *x))
Definition: list-inl.h:183
void Print(int indent, AllocationTracker *tracker)
static bool IsFreeListNode(HeapObject *object)
Definition: spaces-inl.h:355
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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 expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
JSFunction * function() const
Definition: frames-inl.h:284
void AddAll(const List< T, AllocationPolicy > &other, AllocationPolicy allocator=AllocationPolicy())
AllocationTraceNode(AllocationTraceTree *tree, unsigned function_info_index)