blob: 76a441b64d8ec84d70804dff4852e8f128edc3cb [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 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 "frames-inl.h"
31#include "mark-compact.h"
32#include "scopeinfo.h"
33#include "string-stream.h"
34#include "top.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035
36namespace v8 {
37namespace internal {
38
Kristian Monsen80d68ea2010-09-08 11:05:35 +010039PcToCodeCache::PcToCodeCacheEntry
40 PcToCodeCache::cache_[PcToCodeCache::kPcToCodeCacheSize];
41
42int SafeStackFrameIterator::active_count_ = 0;
43
Steve Blocka7e24c12009-10-30 11:49:00 +000044// Iterator that supports traversing the stack handlers of a
45// particular frame. Needs to know the top of the handler chain.
46class StackHandlerIterator BASE_EMBEDDED {
47 public:
48 StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
49 : limit_(frame->fp()), handler_(handler) {
50 // Make sure the handler has already been unwound to this frame.
51 ASSERT(frame->sp() <= handler->address());
52 }
53
54 StackHandler* handler() const { return handler_; }
55
56 bool done() {
57 return handler_ == NULL || handler_->address() > limit_;
58 }
59 void Advance() {
60 ASSERT(!done());
61 handler_ = handler_->next();
62 }
63
64 private:
65 const Address limit_;
66 StackHandler* handler_;
67};
68
69
70// -------------------------------------------------------------------------
71
72
73#define INITIALIZE_SINGLETON(type, field) field##_(this),
74StackFrameIterator::StackFrameIterator()
75 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
76 frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()),
77 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
78 Reset();
79}
80StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
81 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
82 frame_(NULL), handler_(NULL), thread_(t),
83 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
84 Reset();
85}
86StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp)
87 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
88 frame_(NULL), handler_(NULL),
89 thread_(use_top ? Top::GetCurrentThread() : NULL),
90 fp_(use_top ? NULL : fp), sp_(sp),
91 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
92 &StackFrameIterator::AdvanceWithoutHandler) {
93 if (use_top || fp != NULL) {
94 Reset();
95 }
Steve Blocka7e24c12009-10-30 11:49:00 +000096}
97
98#undef INITIALIZE_SINGLETON
99
100
101void StackFrameIterator::AdvanceWithHandler() {
102 ASSERT(!done());
103 // Compute the state of the calling frame before restoring
104 // callee-saved registers and unwinding handlers. This allows the
105 // frame code that computes the caller state to access the top
106 // handler and the value of any callee-saved register if needed.
107 StackFrame::State state;
108 StackFrame::Type type = frame_->GetCallerState(&state);
109
110 // Unwind handlers corresponding to the current frame.
111 StackHandlerIterator it(frame_, handler_);
112 while (!it.done()) it.Advance();
113 handler_ = it.handler();
114
115 // Advance to the calling frame.
116 frame_ = SingletonFor(type, &state);
117
118 // When we're done iterating over the stack frames, the handler
119 // chain must have been completely unwound.
120 ASSERT(!done() || handler_ == NULL);
121}
122
123
124void StackFrameIterator::AdvanceWithoutHandler() {
125 // A simpler version of Advance which doesn't care about handler.
126 ASSERT(!done());
127 StackFrame::State state;
128 StackFrame::Type type = frame_->GetCallerState(&state);
129 frame_ = SingletonFor(type, &state);
130}
131
132
133void StackFrameIterator::Reset() {
134 StackFrame::State state;
135 StackFrame::Type type;
136 if (thread_ != NULL) {
137 type = ExitFrame::GetStateForFramePointer(Top::c_entry_fp(thread_), &state);
138 handler_ = StackHandler::FromAddress(Top::handler(thread_));
139 } else {
140 ASSERT(fp_ != NULL);
141 state.fp = fp_;
142 state.sp = sp_;
143 state.pc_address =
144 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
145 type = StackFrame::ComputeType(&state);
146 if (SingletonFor(type) == NULL) return;
147 }
148 frame_ = SingletonFor(type, &state);
149}
150
151
152StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
153 StackFrame::State* state) {
154 if (type == StackFrame::NONE) return NULL;
155 StackFrame* result = SingletonFor(type);
156 ASSERT(result != NULL);
157 result->state_ = *state;
158 return result;
159}
160
161
162StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
163#define FRAME_TYPE_CASE(type, field) \
164 case StackFrame::type: result = &field##_; break;
165
166 StackFrame* result = NULL;
167 switch (type) {
168 case StackFrame::NONE: return NULL;
169 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
170 default: break;
171 }
172 return result;
173
174#undef FRAME_TYPE_CASE
175}
176
177
178// -------------------------------------------------------------------------
179
180
181StackTraceFrameIterator::StackTraceFrameIterator() {
Leon Clarke4515c472010-02-03 11:58:03 +0000182 if (!done() && !IsValidFrame()) Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +0000183}
184
185
186void StackTraceFrameIterator::Advance() {
187 while (true) {
188 JavaScriptFrameIterator::Advance();
189 if (done()) return;
Leon Clarke4515c472010-02-03 11:58:03 +0000190 if (IsValidFrame()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000191 }
192}
193
Leon Clarke4515c472010-02-03 11:58:03 +0000194bool StackTraceFrameIterator::IsValidFrame() {
195 if (!frame()->function()->IsJSFunction()) return false;
196 Object* script = JSFunction::cast(frame()->function())->shared()->script();
197 // Don't show functions from native scripts to user.
198 return (script->IsScript() &&
199 Script::TYPE_NATIVE != Script::cast(script)->type()->value());
200}
201
Steve Blocka7e24c12009-10-30 11:49:00 +0000202
203// -------------------------------------------------------------------------
204
205
206SafeStackFrameIterator::SafeStackFrameIterator(
207 Address fp, Address sp, Address low_bound, Address high_bound) :
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100208 maintainer_(), low_bound_(low_bound), high_bound_(high_bound),
Steve Blocka7e24c12009-10-30 11:49:00 +0000209 is_valid_top_(
210 IsWithinBounds(low_bound, high_bound,
211 Top::c_entry_fp(Top::GetCurrentThread())) &&
212 Top::handler(Top::GetCurrentThread()) != NULL),
213 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
214 is_working_iterator_(is_valid_top_ || is_valid_fp_),
215 iteration_done_(!is_working_iterator_),
216 iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
217}
218
219
220void SafeStackFrameIterator::Advance() {
221 ASSERT(is_working_iterator_);
222 ASSERT(!done());
223 StackFrame* last_frame = iterator_.frame();
224 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
225 // Before advancing to the next stack frame, perform pointer validity tests
226 iteration_done_ = !IsValidFrame(last_frame) ||
227 !CanIterateHandles(last_frame, iterator_.handler()) ||
228 !IsValidCaller(last_frame);
229 if (iteration_done_) return;
230
231 iterator_.Advance();
232 if (iterator_.done()) return;
233 // Check that we have actually moved to the previous frame in the stack
234 StackFrame* prev_frame = iterator_.frame();
235 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
236}
237
238
239bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
240 StackHandler* handler) {
241 // If StackIterator iterates over StackHandles, verify that
242 // StackHandlerIterator can be instantiated (see StackHandlerIterator
243 // constructor.)
244 return !is_valid_top_ || (frame->sp() <= handler->address());
245}
246
247
248bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
249 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
250}
251
252
253bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
254 StackFrame::State state;
255 if (frame->is_entry() || frame->is_entry_construct()) {
256 // See EntryFrame::GetCallerState. It computes the caller FP address
257 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
258 // sure that caller FP address is valid.
259 Address caller_fp = Memory::Address_at(
260 frame->fp() + EntryFrameConstants::kCallerFPOffset);
261 if (!IsValidStackAddress(caller_fp)) {
262 return false;
263 }
264 } else if (frame->is_arguments_adaptor()) {
265 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
266 // the number of arguments is stored on stack as Smi. We need to check
267 // that it really an Smi.
268 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
269 GetExpression(0);
270 if (!number_of_args->IsSmi()) {
271 return false;
272 }
273 }
274 frame->ComputeCallerState(&state);
275 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
276 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
277}
278
279
280void SafeStackFrameIterator::Reset() {
281 if (is_working_iterator_) {
282 iterator_.Reset();
283 iteration_done_ = false;
284 }
285}
286
287
288// -------------------------------------------------------------------------
289
290
291#ifdef ENABLE_LOGGING_AND_PROFILING
292SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
293 Address fp, Address sp, Address low_bound, Address high_bound) :
294 SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) {
295 if (!done() && !frame()->is_java_script()) Advance();
296}
297
298
299void SafeStackTraceFrameIterator::Advance() {
300 while (true) {
301 SafeJavaScriptFrameIterator::Advance();
302 if (done()) return;
303 if (frame()->is_java_script()) return;
304 }
305}
306#endif
307
308
Steve Blocka7e24c12009-10-30 11:49:00 +0000309bool StackFrame::HasHandler() const {
310 StackHandlerIterator it(this, top_handler());
311 return !it.done();
312}
313
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100314void StackFrame::IteratePc(ObjectVisitor* v,
315 Address* pc_address,
316 Code* holder) {
317 Address pc = *pc_address;
318 ASSERT(holder->contains(pc));
319 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
320 Object* code = holder;
321 v->VisitPointer(&code);
322 if (code != holder) {
323 holder = reinterpret_cast<Code*>(code);
324 pc = holder->instruction_start() + pc_offset;
325 *pc_address = pc;
Steve Blocka7e24c12009-10-30 11:49:00 +0000326 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000327}
328
329
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100330StackFrame::Type StackFrame::ComputeType(State* state) {
331 ASSERT(state->fp != NULL);
332 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
333 return ARGUMENTS_ADAPTOR;
Steve Blocka7e24c12009-10-30 11:49:00 +0000334 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100335 // The marker and function offsets overlap. If the marker isn't a
336 // smi then the frame is a JavaScript frame -- and the marker is
337 // really the function.
338 const int offset = StandardFrameConstants::kMarkerOffset;
339 Object* marker = Memory::Object_at(state->fp + offset);
340 if (!marker->IsSmi()) return JAVA_SCRIPT;
341 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000342}
343
344
Steve Blocka7e24c12009-10-30 11:49:00 +0000345
346StackFrame::Type StackFrame::GetCallerState(State* state) const {
347 ComputeCallerState(state);
348 return ComputeType(state);
349}
350
351
Iain Merrick75681382010-08-19 15:07:18 +0100352Code* EntryFrame::unchecked_code() const {
353 return Heap::raw_unchecked_js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000354}
355
356
357void EntryFrame::ComputeCallerState(State* state) const {
358 GetCallerState(state);
359}
360
361
Steve Block6ded16b2010-05-10 14:33:55 +0100362void EntryFrame::SetCallerFp(Address caller_fp) {
363 const int offset = EntryFrameConstants::kCallerFPOffset;
364 Memory::Address_at(this->fp() + offset) = caller_fp;
365}
366
367
Steve Blocka7e24c12009-10-30 11:49:00 +0000368StackFrame::Type EntryFrame::GetCallerState(State* state) const {
369 const int offset = EntryFrameConstants::kCallerFPOffset;
370 Address fp = Memory::Address_at(this->fp() + offset);
371 return ExitFrame::GetStateForFramePointer(fp, state);
372}
373
374
Iain Merrick75681382010-08-19 15:07:18 +0100375Code* EntryConstructFrame::unchecked_code() const {
376 return Heap::raw_unchecked_js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000377}
378
379
Steve Blockd0582a62009-12-15 09:54:21 +0000380Object*& ExitFrame::code_slot() const {
381 const int offset = ExitFrameConstants::kCodeOffset;
382 return Memory::Object_at(fp() + offset);
383}
384
385
Iain Merrick75681382010-08-19 15:07:18 +0100386Code* ExitFrame::unchecked_code() const {
387 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000388}
389
390
391void ExitFrame::ComputeCallerState(State* state) const {
392 // Setup the caller state.
393 state->sp = caller_sp();
394 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
395 state->pc_address
396 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
397}
398
399
Steve Block6ded16b2010-05-10 14:33:55 +0100400void ExitFrame::SetCallerFp(Address caller_fp) {
401 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
402}
403
404
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100405void ExitFrame::Iterate(ObjectVisitor* v) const {
406 // The arguments are traversed as part of the expression stack of
407 // the calling frame.
408 IteratePc(v, pc_address(), code());
409 v->VisitPointer(&code_slot());
410}
411
412
Steve Blocka7e24c12009-10-30 11:49:00 +0000413Address ExitFrame::GetCallerStackPointer() const {
414 return fp() + ExitFrameConstants::kCallerSPDisplacement;
415}
416
417
Steve Blocka7e24c12009-10-30 11:49:00 +0000418Address StandardFrame::GetExpressionAddress(int n) const {
419 const int offset = StandardFrameConstants::kExpressionsOffset;
420 return fp() + offset - n * kPointerSize;
421}
422
423
424int StandardFrame::ComputeExpressionsCount() const {
425 const int offset =
426 StandardFrameConstants::kExpressionsOffset + kPointerSize;
427 Address base = fp() + offset;
428 Address limit = sp();
429 ASSERT(base >= limit); // stack grows downwards
430 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000431 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000432}
433
434
435void StandardFrame::ComputeCallerState(State* state) const {
436 state->sp = caller_sp();
437 state->fp = caller_fp();
438 state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
439}
440
441
Steve Block6ded16b2010-05-10 14:33:55 +0100442void StandardFrame::SetCallerFp(Address caller_fp) {
443 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
444 caller_fp;
445}
446
447
Steve Blocka7e24c12009-10-30 11:49:00 +0000448bool StandardFrame::IsExpressionInsideHandler(int n) const {
449 Address address = GetExpressionAddress(n);
450 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
451 if (it.handler()->includes(address)) return true;
452 }
453 return false;
454}
455
456
457Object* JavaScriptFrame::GetParameter(int index) const {
458 ASSERT(index >= 0 && index < ComputeParametersCount());
459 const int offset = JavaScriptFrameConstants::kParam0Offset;
460 return Memory::Object_at(caller_sp() + offset - (index * kPointerSize));
461}
462
463
464int JavaScriptFrame::ComputeParametersCount() const {
465 Address base = caller_sp() + JavaScriptFrameConstants::kReceiverOffset;
466 Address limit = fp() + JavaScriptFrameConstants::kSavedRegistersOffset;
Steve Blockd0582a62009-12-15 09:54:21 +0000467 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000468}
469
470
471bool JavaScriptFrame::IsConstructor() const {
472 Address fp = caller_fp();
473 if (has_adapted_arguments()) {
474 // Skip the arguments adaptor frame and look at the real caller.
475 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
476 }
477 return IsConstructFrame(fp);
478}
479
480
Iain Merrick75681382010-08-19 15:07:18 +0100481Code* JavaScriptFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000482 JSFunction* function = JSFunction::cast(this->function());
Iain Merrick75681382010-08-19 15:07:18 +0100483 return function->unchecked_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000484}
485
486
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100487int JavaScriptFrame::GetProvidedParametersCount() const {
488 return ComputeParametersCount();
489}
490
491
492Address JavaScriptFrame::GetCallerStackPointer() const {
493 int arguments;
494 if (Heap::gc_state() != Heap::NOT_IN_GC ||
495 SafeStackFrameIterator::is_active()) {
496 // If the we are currently iterating the safe stack the
497 // arguments for frames are traversed as if they were
498 // expression stack elements of the calling frame. The reason for
499 // this rather strange decision is that we cannot access the
500 // function during mark-compact GCs when objects may have been marked.
501 // In fact accessing heap objects (like function->shared() below)
502 // at all during GC is problematic.
503 arguments = 0;
504 } else {
505 // Compute the number of arguments by getting the number of formal
506 // parameters of the function. We must remember to take the
507 // receiver into account (+1).
508 JSFunction* function = JSFunction::cast(this->function());
509 arguments = function->shared()->formal_parameter_count() + 1;
510 }
511 const int offset = StandardFrameConstants::kCallerSPOffset;
512 return fp() + offset + (arguments * kPointerSize);
513}
514
515
516Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
517 const int arguments = Smi::cast(GetExpression(0))->value();
518 const int offset = StandardFrameConstants::kCallerSPOffset;
519 return fp() + offset + (arguments + 1) * kPointerSize;
520}
521
522
523Address InternalFrame::GetCallerStackPointer() const {
524 // Internal frames have no arguments. The stack pointer of the
525 // caller is at a fixed offset from the frame pointer.
526 return fp() + StandardFrameConstants::kCallerSPOffset;
527}
528
529
Iain Merrick75681382010-08-19 15:07:18 +0100530Code* ArgumentsAdaptorFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000531 return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline);
532}
533
534
Iain Merrick75681382010-08-19 15:07:18 +0100535Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000536 const int offset = InternalFrameConstants::kCodeOffset;
537 Object* code = Memory::Object_at(fp() + offset);
538 ASSERT(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +0100539 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000540}
541
542
543void StackFrame::PrintIndex(StringStream* accumulator,
544 PrintMode mode,
545 int index) {
546 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
547}
548
549
550void JavaScriptFrame::Print(StringStream* accumulator,
551 PrintMode mode,
552 int index) const {
553 HandleScope scope;
554 Object* receiver = this->receiver();
555 Object* function = this->function();
556
557 accumulator->PrintSecurityTokenIfChanged(function);
558 PrintIndex(accumulator, mode, index);
559 Code* code = NULL;
560 if (IsConstructor()) accumulator->Add("new ");
561 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +0100562
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100563 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
564
Steve Block6ded16b2010-05-10 14:33:55 +0100565 if (function->IsJSFunction()) {
566 Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100567 scope_info = Handle<SerializedScopeInfo>(shared->scope_info());
Steve Block6ded16b2010-05-10 14:33:55 +0100568 Object* script_obj = shared->script();
569 if (script_obj->IsScript()) {
570 Handle<Script> script(Script::cast(script_obj));
571 accumulator->Add(" [");
572 accumulator->PrintName(script->name());
573
574 Address pc = this->pc();
575 if (code != NULL && code->kind() == Code::FUNCTION &&
Leon Clarkeac952652010-07-15 11:15:24 +0100576 pc >= code->instruction_start() && pc < code->instruction_end()) {
Steve Block6ded16b2010-05-10 14:33:55 +0100577 int source_pos = code->SourcePosition(pc);
578 int line = GetScriptLineNumberSafe(script, source_pos) + 1;
579 accumulator->Add(":%d", line);
580 } else {
581 int function_start_pos = shared->start_position();
582 int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
583 accumulator->Add(":~%d", line);
584 }
585
586 accumulator->Add("] ");
587 }
588 }
589
Steve Blocka7e24c12009-10-30 11:49:00 +0000590 accumulator->Add("(this=%o", receiver);
591
592 // Get scope information for nicer output, if possible. If code is
593 // NULL, or doesn't contain scope info, info will return 0 for the
594 // number of parameters, stack slots, or context slots.
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100595 ScopeInfo<PreallocatedStorage> info(*scope_info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000596
597 // Print the parameters.
598 int parameters_count = ComputeParametersCount();
599 for (int i = 0; i < parameters_count; i++) {
600 accumulator->Add(",");
601 // If we have a name for the parameter we print it. Nameless
602 // parameters are either because we have more actual parameters
603 // than formal parameters or because we have no scope information.
604 if (i < info.number_of_parameters()) {
605 accumulator->PrintName(*info.parameter_name(i));
606 accumulator->Add("=");
607 }
608 accumulator->Add("%o", GetParameter(i));
609 }
610
611 accumulator->Add(")");
612 if (mode == OVERVIEW) {
613 accumulator->Add("\n");
614 return;
615 }
616 accumulator->Add(" {\n");
617
618 // Compute the number of locals and expression stack elements.
619 int stack_locals_count = info.number_of_stack_slots();
620 int heap_locals_count = info.number_of_context_slots();
621 int expressions_count = ComputeExpressionsCount();
622
623 // Print stack-allocated local variables.
624 if (stack_locals_count > 0) {
625 accumulator->Add(" // stack-allocated locals\n");
626 }
627 for (int i = 0; i < stack_locals_count; i++) {
628 accumulator->Add(" var ");
629 accumulator->PrintName(*info.stack_slot_name(i));
630 accumulator->Add(" = ");
631 if (i < expressions_count) {
632 accumulator->Add("%o", GetExpression(i));
633 } else {
634 accumulator->Add("// no expression found - inconsistent frame?");
635 }
636 accumulator->Add("\n");
637 }
638
639 // Try to get hold of the context of this frame.
640 Context* context = NULL;
641 if (this->context() != NULL && this->context()->IsContext()) {
642 context = Context::cast(this->context());
643 }
644
645 // Print heap-allocated local variables.
646 if (heap_locals_count > Context::MIN_CONTEXT_SLOTS) {
647 accumulator->Add(" // heap-allocated locals\n");
648 }
649 for (int i = Context::MIN_CONTEXT_SLOTS; i < heap_locals_count; i++) {
650 accumulator->Add(" var ");
651 accumulator->PrintName(*info.context_slot_name(i));
652 accumulator->Add(" = ");
653 if (context != NULL) {
654 if (i < context->length()) {
655 accumulator->Add("%o", context->get(i));
656 } else {
657 accumulator->Add(
658 "// warning: missing context slot - inconsistent frame?");
659 }
660 } else {
661 accumulator->Add("// warning: no context found - inconsistent frame?");
662 }
663 accumulator->Add("\n");
664 }
665
666 // Print the expression stack.
667 int expressions_start = stack_locals_count;
668 if (expressions_start < expressions_count) {
669 accumulator->Add(" // expression stack (top to bottom)\n");
670 }
671 for (int i = expressions_count - 1; i >= expressions_start; i--) {
672 if (IsExpressionInsideHandler(i)) continue;
673 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
674 }
675
676 // Print details about the function.
677 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
678 SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
679 accumulator->Add("--------- s o u r c e c o d e ---------\n");
680 shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
681 accumulator->Add("\n-----------------------------------------\n");
682 }
683
684 accumulator->Add("}\n\n");
685}
686
687
688void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
689 PrintMode mode,
690 int index) const {
691 int actual = ComputeParametersCount();
692 int expected = -1;
693 Object* function = this->function();
694 if (function->IsJSFunction()) {
695 expected = JSFunction::cast(function)->shared()->formal_parameter_count();
696 }
697
698 PrintIndex(accumulator, mode, index);
699 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
700 if (mode == OVERVIEW) {
701 accumulator->Add("\n");
702 return;
703 }
704 accumulator->Add(" {\n");
705
706 // Print actual arguments.
707 if (actual > 0) accumulator->Add(" // actual arguments\n");
708 for (int i = 0; i < actual; i++) {
709 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
710 if (expected != -1 && i >= expected) {
711 accumulator->Add(" // not passed to callee");
712 }
713 accumulator->Add("\n");
714 }
715
716 accumulator->Add("}\n\n");
717}
718
719
720void EntryFrame::Iterate(ObjectVisitor* v) const {
721 StackHandlerIterator it(this, top_handler());
722 ASSERT(!it.done());
723 StackHandler* handler = it.handler();
724 ASSERT(handler->is_entry());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100725 handler->Iterate(v, code());
Steve Blocka7e24c12009-10-30 11:49:00 +0000726#ifdef DEBUG
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100727 // Make sure that the entry frame does not contain more than one
728 // stack handler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000729 it.Advance();
730 ASSERT(it.done());
731#endif
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100732 IteratePc(v, pc_address(), code());
Steve Blocka7e24c12009-10-30 11:49:00 +0000733}
734
735
736void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
737 const int offset = StandardFrameConstants::kContextOffset;
738 Object** base = &Memory::Object_at(sp());
739 Object** limit = &Memory::Object_at(fp() + offset) + 1;
740 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
741 StackHandler* handler = it.handler();
742 // Traverse pointers down to - but not including - the next
743 // handler in the handler chain. Update the base to skip the
744 // handler and allow the handler to traverse its own pointers.
745 const Address address = handler->address();
746 v->VisitPointers(base, reinterpret_cast<Object**>(address));
747 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
748 // Traverse the pointers in the handler itself.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100749 handler->Iterate(v, code());
Steve Blocka7e24c12009-10-30 11:49:00 +0000750 }
751 v->VisitPointers(base, limit);
752}
753
754
755void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
756 IterateExpressions(v);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100757 IteratePc(v, pc_address(), code());
Steve Blocka7e24c12009-10-30 11:49:00 +0000758
759 // Traverse callee-saved registers, receiver, and parameters.
760 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset;
761 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset;
762 Object** base = &Memory::Object_at(fp() + kBaseOffset);
763 Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1;
764 v->VisitPointers(base, limit);
765}
766
767
768void InternalFrame::Iterate(ObjectVisitor* v) const {
769 // Internal frames only have object pointers on the expression stack
770 // as they never have any arguments.
771 IterateExpressions(v);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100772 IteratePc(v, pc_address(), code());
Steve Blocka7e24c12009-10-30 11:49:00 +0000773}
774
775
776// -------------------------------------------------------------------------
777
778
779JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
780 ASSERT(n >= 0);
781 for (int i = 0; i <= n; i++) {
782 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
783 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
784 iterator_.Advance();
785 }
786 UNREACHABLE();
787 return NULL;
788}
789
790
791// -------------------------------------------------------------------------
792
793
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100794Code* PcToCodeCache::GcSafeCastToCode(HeapObject* object, Address pc) {
795 Code* code = reinterpret_cast<Code*>(object);
796 ASSERT(code != NULL && code->contains(pc));
797 return code;
798}
799
800
801Code* PcToCodeCache::GcSafeFindCodeForPc(Address pc) {
802 // Check if the pc points into a large object chunk.
803 LargeObjectChunk* chunk = Heap::lo_space()->FindChunkContainingPc(pc);
804 if (chunk != NULL) return GcSafeCastToCode(chunk->GetObject(), pc);
805
806 // Iterate through the 8K page until we reach the end or find an
807 // object starting after the pc.
808 Page* page = Page::FromAddress(pc);
809 HeapObjectIterator iterator(page, Heap::GcSafeSizeOfOldObjectFunction());
810 HeapObject* previous = NULL;
811 while (true) {
812 HeapObject* next = iterator.next();
813 if (next == NULL || next->address() >= pc) {
814 return GcSafeCastToCode(previous, pc);
815 }
816 previous = next;
817 }
818}
819
820PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) {
821 Counters::pc_to_code.Increment();
822 ASSERT(IsPowerOf2(kPcToCodeCacheSize));
823 uint32_t hash = ComputeIntegerHash(
824 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc)));
825 uint32_t index = hash & (kPcToCodeCacheSize - 1);
826 PcToCodeCacheEntry* entry = cache(index);
827 if (entry->pc == pc) {
828 Counters::pc_to_code_cached.Increment();
829 ASSERT(entry->code == GcSafeFindCodeForPc(pc));
830 } else {
831 // Because this code may be interrupted by a profiling signal that
832 // also queries the cache, we cannot update pc before the code has
833 // been set. Otherwise, we risk trying to use a cache entry before
834 // the code has been computed.
835 entry->code = GcSafeFindCodeForPc(pc);
836 entry->pc = pc;
837 }
838 return entry;
839}
840
841
842// -------------------------------------------------------------------------
843
Steve Blocka7e24c12009-10-30 11:49:00 +0000844int NumRegs(RegList reglist) {
845 int n = 0;
846 while (reglist != 0) {
847 n++;
848 reglist &= reglist - 1; // clear one bit
849 }
850 return n;
851}
852
853
854int JSCallerSavedCode(int n) {
855 static int reg_code[kNumJSCallerSaved];
856 static bool initialized = false;
857 if (!initialized) {
858 initialized = true;
859 int i = 0;
860 for (int r = 0; r < kNumRegs; r++)
861 if ((kJSCallerSaved & (1 << r)) != 0)
862 reg_code[i++] = r;
863
864 ASSERT(i == kNumJSCallerSaved);
865 }
866 ASSERT(0 <= n && n < kNumJSCallerSaved);
867 return reg_code[n];
868}
869
870
Steve Block6ded16b2010-05-10 14:33:55 +0100871#define DEFINE_WRAPPER(type, field) \
872class field##_Wrapper : public ZoneObject { \
873 public: /* NOLINT */ \
874 field##_Wrapper(const field& original) : frame_(original) { \
875 } \
876 field frame_; \
877};
878STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
879#undef DEFINE_WRAPPER
880
881static StackFrame* AllocateFrameCopy(StackFrame* frame) {
882#define FRAME_TYPE_CASE(type, field) \
883 case StackFrame::type: { \
884 field##_Wrapper* wrapper = \
885 new field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
886 return &wrapper->frame_; \
887 }
888
889 switch (frame->type()) {
890 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
891 default: UNREACHABLE();
892 }
893#undef FRAME_TYPE_CASE
894 return NULL;
895}
896
897Vector<StackFrame*> CreateStackMap() {
898 ZoneList<StackFrame*> list(10);
899 for (StackFrameIterator it; !it.done(); it.Advance()) {
900 StackFrame* frame = AllocateFrameCopy(it.frame());
901 list.Add(frame);
902 }
903 return list.ToVector();
904}
905
906
Steve Blocka7e24c12009-10-30 11:49:00 +0000907} } // namespace v8::internal