blob: 79aa2507fba0c31230192a6bb6754a3d5599ce95 [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
Ben Murdochb0fe1622011-05-05 13:52:32 +010030#include "ast.h"
31#include "deoptimizer.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "frames-inl.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010033#include "full-codegen.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034#include "mark-compact.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010035#include "safepoint-table.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000036#include "scopeinfo.h"
37#include "string-stream.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038
39namespace v8 {
40namespace internal {
41
Kristian Monsen80d68ea2010-09-08 11:05:35 +010042
43int SafeStackFrameIterator::active_count_ = 0;
44
Steve Blocka7e24c12009-10-30 11:49:00 +000045// Iterator that supports traversing the stack handlers of a
46// particular frame. Needs to know the top of the handler chain.
47class StackHandlerIterator BASE_EMBEDDED {
48 public:
49 StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
50 : limit_(frame->fp()), handler_(handler) {
51 // Make sure the handler has already been unwound to this frame.
52 ASSERT(frame->sp() <= handler->address());
53 }
54
55 StackHandler* handler() const { return handler_; }
56
57 bool done() {
58 return handler_ == NULL || handler_->address() > limit_;
59 }
60 void Advance() {
61 ASSERT(!done());
62 handler_ = handler_->next();
63 }
64
65 private:
66 const Address limit_;
67 StackHandler* handler_;
68};
69
70
71// -------------------------------------------------------------------------
72
73
74#define INITIALIZE_SINGLETON(type, field) field##_(this),
75StackFrameIterator::StackFrameIterator()
76 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
Steve Block44f0eee2011-05-26 01:26:41 +010077 frame_(NULL), handler_(NULL),
78 thread_(Isolate::Current()->thread_local_top()),
Steve Blocka7e24c12009-10-30 11:49:00 +000079 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
80 Reset();
81}
82StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
83 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
84 frame_(NULL), handler_(NULL), thread_(t),
85 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
86 Reset();
87}
Steve Block44f0eee2011-05-26 01:26:41 +010088StackFrameIterator::StackFrameIterator(Isolate* isolate,
89 bool use_top, Address fp, Address sp)
Steve Blocka7e24c12009-10-30 11:49:00 +000090 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
91 frame_(NULL), handler_(NULL),
Steve Block44f0eee2011-05-26 01:26:41 +010092 thread_(use_top ? isolate->thread_local_top() : NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +000093 fp_(use_top ? NULL : fp), sp_(sp),
94 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
95 &StackFrameIterator::AdvanceWithoutHandler) {
96 if (use_top || fp != NULL) {
97 Reset();
98 }
Steve Blocka7e24c12009-10-30 11:49:00 +000099}
100
101#undef INITIALIZE_SINGLETON
102
103
104void StackFrameIterator::AdvanceWithHandler() {
105 ASSERT(!done());
106 // Compute the state of the calling frame before restoring
107 // callee-saved registers and unwinding handlers. This allows the
108 // frame code that computes the caller state to access the top
109 // handler and the value of any callee-saved register if needed.
110 StackFrame::State state;
111 StackFrame::Type type = frame_->GetCallerState(&state);
112
113 // Unwind handlers corresponding to the current frame.
114 StackHandlerIterator it(frame_, handler_);
115 while (!it.done()) it.Advance();
116 handler_ = it.handler();
117
118 // Advance to the calling frame.
119 frame_ = SingletonFor(type, &state);
120
121 // When we're done iterating over the stack frames, the handler
122 // chain must have been completely unwound.
123 ASSERT(!done() || handler_ == NULL);
124}
125
126
127void StackFrameIterator::AdvanceWithoutHandler() {
128 // A simpler version of Advance which doesn't care about handler.
129 ASSERT(!done());
130 StackFrame::State state;
131 StackFrame::Type type = frame_->GetCallerState(&state);
132 frame_ = SingletonFor(type, &state);
133}
134
135
136void StackFrameIterator::Reset() {
137 StackFrame::State state;
138 StackFrame::Type type;
139 if (thread_ != NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100140 type = ExitFrame::GetStateForFramePointer(
141 Isolate::c_entry_fp(thread_), &state);
142 handler_ = StackHandler::FromAddress(
143 Isolate::handler(thread_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000144 } else {
145 ASSERT(fp_ != NULL);
146 state.fp = fp_;
147 state.sp = sp_;
148 state.pc_address =
149 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
150 type = StackFrame::ComputeType(&state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000151 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100152 if (SingletonFor(type) == NULL) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000153 frame_ = SingletonFor(type, &state);
154}
155
156
157StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
158 StackFrame::State* state) {
159 if (type == StackFrame::NONE) return NULL;
160 StackFrame* result = SingletonFor(type);
161 ASSERT(result != NULL);
162 result->state_ = *state;
163 return result;
164}
165
166
167StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
168#define FRAME_TYPE_CASE(type, field) \
169 case StackFrame::type: result = &field##_; break;
170
171 StackFrame* result = NULL;
172 switch (type) {
173 case StackFrame::NONE: return NULL;
174 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
175 default: break;
176 }
177 return result;
178
179#undef FRAME_TYPE_CASE
180}
181
182
183// -------------------------------------------------------------------------
184
185
186StackTraceFrameIterator::StackTraceFrameIterator() {
Leon Clarke4515c472010-02-03 11:58:03 +0000187 if (!done() && !IsValidFrame()) Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +0000188}
189
190
191void StackTraceFrameIterator::Advance() {
192 while (true) {
193 JavaScriptFrameIterator::Advance();
194 if (done()) return;
Leon Clarke4515c472010-02-03 11:58:03 +0000195 if (IsValidFrame()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000196 }
197}
198
Leon Clarke4515c472010-02-03 11:58:03 +0000199bool StackTraceFrameIterator::IsValidFrame() {
200 if (!frame()->function()->IsJSFunction()) return false;
201 Object* script = JSFunction::cast(frame()->function())->shared()->script();
202 // Don't show functions from native scripts to user.
203 return (script->IsScript() &&
204 Script::TYPE_NATIVE != Script::cast(script)->type()->value());
205}
206
Steve Blocka7e24c12009-10-30 11:49:00 +0000207
208// -------------------------------------------------------------------------
209
210
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100211bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
212 if (!validator_.IsValid(fp)) return false;
213 Address sp = ExitFrame::ComputeStackPointer(fp);
214 if (!validator_.IsValid(sp)) return false;
215 StackFrame::State state;
216 ExitFrame::FillState(fp, sp, &state);
217 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
218 return false;
219 }
220 return *state.pc_address != NULL;
221}
222
223
Steve Blocka7e24c12009-10-30 11:49:00 +0000224SafeStackFrameIterator::SafeStackFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100225 Isolate* isolate,
Steve Blocka7e24c12009-10-30 11:49:00 +0000226 Address fp, Address sp, Address low_bound, Address high_bound) :
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100227 maintainer_(),
228 stack_validator_(low_bound, high_bound),
Steve Block44f0eee2011-05-26 01:26:41 +0100229 is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
Steve Blocka7e24c12009-10-30 11:49:00 +0000230 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
231 is_working_iterator_(is_valid_top_ || is_valid_fp_),
232 iteration_done_(!is_working_iterator_),
Steve Block44f0eee2011-05-26 01:26:41 +0100233 iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000234}
235
236
Steve Block44f0eee2011-05-26 01:26:41 +0100237bool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
238 Address low_bound, Address high_bound) {
239 ThreadLocalTop* top = isolate->thread_local_top();
240 Address fp = Isolate::c_entry_fp(top);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100241 ExitFrameValidator validator(low_bound, high_bound);
242 if (!validator.IsValidFP(fp)) return false;
Steve Block44f0eee2011-05-26 01:26:41 +0100243 return Isolate::handler(top) != NULL;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100244}
245
246
Steve Blocka7e24c12009-10-30 11:49:00 +0000247void SafeStackFrameIterator::Advance() {
248 ASSERT(is_working_iterator_);
249 ASSERT(!done());
250 StackFrame* last_frame = iterator_.frame();
251 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
252 // Before advancing to the next stack frame, perform pointer validity tests
253 iteration_done_ = !IsValidFrame(last_frame) ||
254 !CanIterateHandles(last_frame, iterator_.handler()) ||
255 !IsValidCaller(last_frame);
256 if (iteration_done_) return;
257
258 iterator_.Advance();
259 if (iterator_.done()) return;
260 // Check that we have actually moved to the previous frame in the stack
261 StackFrame* prev_frame = iterator_.frame();
262 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
263}
264
265
266bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
267 StackHandler* handler) {
268 // If StackIterator iterates over StackHandles, verify that
269 // StackHandlerIterator can be instantiated (see StackHandlerIterator
270 // constructor.)
271 return !is_valid_top_ || (frame->sp() <= handler->address());
272}
273
274
275bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
276 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
277}
278
279
280bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
281 StackFrame::State state;
282 if (frame->is_entry() || frame->is_entry_construct()) {
283 // See EntryFrame::GetCallerState. It computes the caller FP address
284 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
285 // sure that caller FP address is valid.
286 Address caller_fp = Memory::Address_at(
287 frame->fp() + EntryFrameConstants::kCallerFPOffset);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100288 ExitFrameValidator validator(stack_validator_);
289 if (!validator.IsValidFP(caller_fp)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000290 } else if (frame->is_arguments_adaptor()) {
291 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
292 // the number of arguments is stored on stack as Smi. We need to check
293 // that it really an Smi.
294 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
295 GetExpression(0);
296 if (!number_of_args->IsSmi()) {
297 return false;
298 }
299 }
300 frame->ComputeCallerState(&state);
301 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
302 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
303}
304
305
306void SafeStackFrameIterator::Reset() {
307 if (is_working_iterator_) {
308 iterator_.Reset();
309 iteration_done_ = false;
310 }
311}
312
313
314// -------------------------------------------------------------------------
315
316
317#ifdef ENABLE_LOGGING_AND_PROFILING
318SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100319 Isolate* isolate,
Steve Blocka7e24c12009-10-30 11:49:00 +0000320 Address fp, Address sp, Address low_bound, Address high_bound) :
Steve Block44f0eee2011-05-26 01:26:41 +0100321 SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 if (!done() && !frame()->is_java_script()) Advance();
323}
324
325
326void SafeStackTraceFrameIterator::Advance() {
327 while (true) {
328 SafeJavaScriptFrameIterator::Advance();
329 if (done()) return;
330 if (frame()->is_java_script()) return;
331 }
332}
333#endif
334
335
Ben Murdochb0fe1622011-05-05 13:52:32 +0100336Code* StackFrame::GetSafepointData(Address pc,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100337 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100338 unsigned* stack_slots) {
Steve Block44f0eee2011-05-26 01:26:41 +0100339 Isolate* isolate = Isolate::Current();
340 PcToCodeCache::PcToCodeCacheEntry* entry =
341 isolate->pc_to_code_cache()->GetCacheEntry(pc);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100342 SafepointEntry cached_safepoint_entry = entry->safepoint_entry;
343 if (!entry->safepoint_entry.is_valid()) {
344 entry->safepoint_entry = entry->code->GetSafepointEntry(pc);
345 ASSERT(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100346 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100347 ASSERT(entry->safepoint_entry.Equals(entry->code->GetSafepointEntry(pc)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100348 }
349
350 // Fill in the results and return the code.
351 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100352 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100353 *stack_slots = code->stack_slots();
354 return code;
355}
356
357
Steve Blocka7e24c12009-10-30 11:49:00 +0000358bool StackFrame::HasHandler() const {
359 StackHandlerIterator it(this, top_handler());
360 return !it.done();
361}
362
Ben Murdochb0fe1622011-05-05 13:52:32 +0100363
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100364void StackFrame::IteratePc(ObjectVisitor* v,
365 Address* pc_address,
366 Code* holder) {
367 Address pc = *pc_address;
368 ASSERT(holder->contains(pc));
369 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
370 Object* code = holder;
371 v->VisitPointer(&code);
372 if (code != holder) {
373 holder = reinterpret_cast<Code*>(code);
374 pc = holder->instruction_start() + pc_offset;
375 *pc_address = pc;
Steve Blocka7e24c12009-10-30 11:49:00 +0000376 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000377}
378
379
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100380StackFrame::Type StackFrame::ComputeType(State* state) {
381 ASSERT(state->fp != NULL);
382 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
383 return ARGUMENTS_ADAPTOR;
Steve Blocka7e24c12009-10-30 11:49:00 +0000384 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100385 // The marker and function offsets overlap. If the marker isn't a
386 // smi then the frame is a JavaScript frame -- and the marker is
387 // really the function.
388 const int offset = StandardFrameConstants::kMarkerOffset;
389 Object* marker = Memory::Object_at(state->fp + offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100390 if (!marker->IsSmi()) {
391 // If we're using a "safe" stack iterator, we treat optimized
392 // frames as normal JavaScript frames to avoid having to look
393 // into the heap to determine the state. This is safe as long
394 // as nobody tries to GC...
395 if (SafeStackFrameIterator::is_active()) return JAVA_SCRIPT;
Steve Block44f0eee2011-05-26 01:26:41 +0100396 Code::Kind kind = GetContainingCode(Isolate::Current(),
397 *(state->pc_address))->kind();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100398 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
399 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
400 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100401 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000402}
403
404
Steve Blocka7e24c12009-10-30 11:49:00 +0000405
406StackFrame::Type StackFrame::GetCallerState(State* state) const {
407 ComputeCallerState(state);
408 return ComputeType(state);
409}
410
411
Iain Merrick75681382010-08-19 15:07:18 +0100412Code* EntryFrame::unchecked_code() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100413 return HEAP->raw_unchecked_js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000414}
415
416
417void EntryFrame::ComputeCallerState(State* state) const {
418 GetCallerState(state);
419}
420
421
Steve Block6ded16b2010-05-10 14:33:55 +0100422void EntryFrame::SetCallerFp(Address caller_fp) {
423 const int offset = EntryFrameConstants::kCallerFPOffset;
424 Memory::Address_at(this->fp() + offset) = caller_fp;
425}
426
427
Steve Blocka7e24c12009-10-30 11:49:00 +0000428StackFrame::Type EntryFrame::GetCallerState(State* state) const {
429 const int offset = EntryFrameConstants::kCallerFPOffset;
430 Address fp = Memory::Address_at(this->fp() + offset);
431 return ExitFrame::GetStateForFramePointer(fp, state);
432}
433
434
Iain Merrick75681382010-08-19 15:07:18 +0100435Code* EntryConstructFrame::unchecked_code() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100436 return HEAP->raw_unchecked_js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000437}
438
439
Steve Blockd0582a62009-12-15 09:54:21 +0000440Object*& ExitFrame::code_slot() const {
441 const int offset = ExitFrameConstants::kCodeOffset;
442 return Memory::Object_at(fp() + offset);
443}
444
445
Iain Merrick75681382010-08-19 15:07:18 +0100446Code* ExitFrame::unchecked_code() const {
447 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000448}
449
450
451void ExitFrame::ComputeCallerState(State* state) const {
452 // Setup the caller state.
453 state->sp = caller_sp();
454 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
455 state->pc_address
456 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
457}
458
459
Steve Block6ded16b2010-05-10 14:33:55 +0100460void ExitFrame::SetCallerFp(Address caller_fp) {
461 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
462}
463
464
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100465void ExitFrame::Iterate(ObjectVisitor* v) const {
466 // The arguments are traversed as part of the expression stack of
467 // the calling frame.
Steve Block44f0eee2011-05-26 01:26:41 +0100468 IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100469 v->VisitPointer(&code_slot());
470}
471
472
Steve Blocka7e24c12009-10-30 11:49:00 +0000473Address ExitFrame::GetCallerStackPointer() const {
474 return fp() + ExitFrameConstants::kCallerSPDisplacement;
475}
476
477
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100478StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
479 if (fp == 0) return NONE;
480 Address sp = ComputeStackPointer(fp);
481 FillState(fp, sp, state);
482 ASSERT(*state->pc_address != NULL);
483 return EXIT;
484}
485
486
487void ExitFrame::FillState(Address fp, Address sp, State* state) {
488 state->sp = sp;
489 state->fp = fp;
490 state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
491}
492
493
Steve Blocka7e24c12009-10-30 11:49:00 +0000494Address StandardFrame::GetExpressionAddress(int n) const {
495 const int offset = StandardFrameConstants::kExpressionsOffset;
496 return fp() + offset - n * kPointerSize;
497}
498
499
500int StandardFrame::ComputeExpressionsCount() const {
501 const int offset =
502 StandardFrameConstants::kExpressionsOffset + kPointerSize;
503 Address base = fp() + offset;
504 Address limit = sp();
505 ASSERT(base >= limit); // stack grows downwards
506 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000507 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000508}
509
510
511void StandardFrame::ComputeCallerState(State* state) const {
512 state->sp = caller_sp();
513 state->fp = caller_fp();
514 state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
515}
516
517
Steve Block6ded16b2010-05-10 14:33:55 +0100518void StandardFrame::SetCallerFp(Address caller_fp) {
519 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
520 caller_fp;
521}
522
523
Steve Blocka7e24c12009-10-30 11:49:00 +0000524bool StandardFrame::IsExpressionInsideHandler(int n) const {
525 Address address = GetExpressionAddress(n);
526 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
527 if (it.handler()->includes(address)) return true;
528 }
529 return false;
530}
531
532
Ben Murdochb0fe1622011-05-05 13:52:32 +0100533void OptimizedFrame::Iterate(ObjectVisitor* v) const {
534#ifdef DEBUG
535 // Make sure that optimized frames do not contain any stack handlers.
536 StackHandlerIterator it(this, top_handler());
537 ASSERT(it.done());
538#endif
539
540 // Make sure that we're not doing "safe" stack frame iteration. We cannot
541 // possibly find pointers in optimized frames in that state.
542 ASSERT(!SafeStackFrameIterator::is_active());
543
544 // Compute the safepoint information.
545 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100546 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100547 Code* code = StackFrame::GetSafepointData(
548 pc(), &safepoint_entry, &stack_slots);
549 unsigned slot_space = stack_slots * kPointerSize;
550
551 // Visit the outgoing parameters. This is usually dealt with by the
552 // callee, but while GC'ing we artificially lower the number of
553 // arguments to zero and let the caller deal with it.
554 Object** parameters_base = &Memory::Object_at(sp());
555 Object** parameters_limit = &Memory::Object_at(
556 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
557
Ben Murdochb8e0da22011-05-16 14:20:40 +0100558 // Visit the parameters that may be on top of the saved registers.
559 if (safepoint_entry.argument_count() > 0) {
560 v->VisitPointers(parameters_base,
561 parameters_base + safepoint_entry.argument_count());
562 parameters_base += safepoint_entry.argument_count();
563 }
564
565 // Skip saved double registers.
566 if (safepoint_entry.has_doubles()) {
567 parameters_base += DoubleRegister::kNumAllocatableRegisters *
568 kDoubleSize / kPointerSize;
569 }
570
Ben Murdochb0fe1622011-05-05 13:52:32 +0100571 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100572 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100573 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100574 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100575 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
576 v->VisitPointer(parameters_base + reg_stack_index);
577 }
578 }
579 // Skip the words containing the register values.
580 parameters_base += kNumSafepointRegisters;
581 }
582
583 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100584 uint8_t* safepoint_bits = safepoint_entry.bits();
585 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100586
587 // Visit the rest of the parameters.
588 v->VisitPointers(parameters_base, parameters_limit);
589
590 // Visit pointer spill slots and locals.
591 for (unsigned index = 0; index < stack_slots; index++) {
592 int byte_index = index >> kBitsPerByteLog2;
593 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100594 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100595 v->VisitPointer(parameters_limit + index);
596 }
597 }
598
599 // Visit the context and the function.
600 Object** fixed_base = &Memory::Object_at(
601 fp() + JavaScriptFrameConstants::kFunctionOffset);
602 Object** fixed_limit = &Memory::Object_at(fp());
603 v->VisitPointers(fixed_base, fixed_limit);
604
605 // Visit the return address in the callee and incoming arguments.
606 IteratePc(v, pc_address(), code);
607 IterateArguments(v);
608}
609
610
Steve Blocka7e24c12009-10-30 11:49:00 +0000611Object* JavaScriptFrame::GetParameter(int index) const {
612 ASSERT(index >= 0 && index < ComputeParametersCount());
613 const int offset = JavaScriptFrameConstants::kParam0Offset;
614 return Memory::Object_at(caller_sp() + offset - (index * kPointerSize));
615}
616
617
618int JavaScriptFrame::ComputeParametersCount() const {
619 Address base = caller_sp() + JavaScriptFrameConstants::kReceiverOffset;
620 Address limit = fp() + JavaScriptFrameConstants::kSavedRegistersOffset;
Steve Blockd0582a62009-12-15 09:54:21 +0000621 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000622}
623
624
625bool JavaScriptFrame::IsConstructor() const {
626 Address fp = caller_fp();
627 if (has_adapted_arguments()) {
628 // Skip the arguments adaptor frame and look at the real caller.
629 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
630 }
631 return IsConstructFrame(fp);
632}
633
634
Iain Merrick75681382010-08-19 15:07:18 +0100635Code* JavaScriptFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000636 JSFunction* function = JSFunction::cast(this->function());
Iain Merrick75681382010-08-19 15:07:18 +0100637 return function->unchecked_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000638}
639
640
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100641Address JavaScriptFrame::GetCallerStackPointer() const {
642 int arguments;
Steve Block44f0eee2011-05-26 01:26:41 +0100643 if (SafeStackFrameIterator::is_active() ||
644 HEAP->gc_state() != Heap::NOT_IN_GC) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100645 // If the we are currently iterating the safe stack the
646 // arguments for frames are traversed as if they were
647 // expression stack elements of the calling frame. The reason for
648 // this rather strange decision is that we cannot access the
649 // function during mark-compact GCs when objects may have been marked.
650 // In fact accessing heap objects (like function->shared() below)
651 // at all during GC is problematic.
652 arguments = 0;
653 } else {
654 // Compute the number of arguments by getting the number of formal
655 // parameters of the function. We must remember to take the
656 // receiver into account (+1).
657 JSFunction* function = JSFunction::cast(this->function());
658 arguments = function->shared()->formal_parameter_count() + 1;
659 }
660 const int offset = StandardFrameConstants::kCallerSPOffset;
661 return fp() + offset + (arguments * kPointerSize);
662}
663
664
Ben Murdochb0fe1622011-05-05 13:52:32 +0100665void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
666 ASSERT(functions->length() == 0);
667 functions->Add(JSFunction::cast(function()));
668}
669
670
671void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
672 ASSERT(functions->length() == 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100673 Code* code_pointer = LookupCode(Isolate::Current());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100674 int offset = static_cast<int>(pc() - code_pointer->address());
675 FrameSummary summary(receiver(),
676 JSFunction::cast(function()),
677 code_pointer,
678 offset,
679 IsConstructor());
680 functions->Add(summary);
681}
682
683
684void FrameSummary::Print() {
685 PrintF("receiver: ");
686 receiver_->ShortPrint();
687 PrintF("\nfunction: ");
688 function_->shared()->DebugName()->ShortPrint();
689 PrintF("\ncode: ");
690 code_->ShortPrint();
691 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
692 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
693 PrintF("\npc: %d\n", offset_);
694}
695
696
697void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
698 ASSERT(frames->length() == 0);
699 ASSERT(is_optimized());
700
Steve Block1e0659c2011-05-24 12:43:12 +0100701 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100702 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
703
704 // BUG(3243555): Since we don't have a lazy-deopt registered at
705 // throw-statements, we can't use the translation at the call-site of
706 // throw. An entry with no deoptimization index indicates a call-site
707 // without a lazy-deopt. As a consequence we are not allowed to inline
708 // functions containing throw.
709 if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
710 JavaScriptFrame::Summarize(frames);
711 return;
712 }
713
714 TranslationIterator it(data->TranslationByteArray(),
715 data->TranslationIndex(deopt_index)->value());
716 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
717 ASSERT(opcode == Translation::BEGIN);
718 int frame_count = it.Next();
719
720 // We create the summary in reverse order because the frames
721 // in the deoptimization translation are ordered bottom-to-top.
722 int i = frame_count;
723 while (i > 0) {
724 opcode = static_cast<Translation::Opcode>(it.Next());
725 if (opcode == Translation::FRAME) {
726 // We don't inline constructor calls, so only the first, outermost
727 // frame can be a constructor frame in case of inlining.
728 bool is_constructor = (i == frame_count) && IsConstructor();
729
730 i--;
731 int ast_id = it.Next();
732 int function_id = it.Next();
733 it.Next(); // Skip height.
734 JSFunction* function =
735 JSFunction::cast(data->LiteralArray()->get(function_id));
736
737 // The translation commands are ordered and the receiver is always
738 // at the first position. Since we are always at a call when we need
739 // to construct a stack trace, the receiver is always in a stack slot.
740 opcode = static_cast<Translation::Opcode>(it.Next());
741 ASSERT(opcode == Translation::STACK_SLOT);
742 int input_slot_index = it.Next();
743
744 // Get the correct receiver in the optimized frame.
745 Object* receiver = NULL;
746 // Positive index means the value is spilled to the locals area. Negative
747 // means it is stored in the incoming parameter area.
748 if (input_slot_index >= 0) {
749 receiver = GetExpression(input_slot_index);
750 } else {
751 // Index -1 overlaps with last parameter, -n with the first parameter,
752 // (-n - 1) with the receiver with n being the number of parameters
753 // of the outermost, optimized frame.
754 int parameter_count = ComputeParametersCount();
755 int parameter_index = input_slot_index + parameter_count;
756 receiver = (parameter_index == -1)
757 ? this->receiver()
758 : this->GetParameter(parameter_index);
759 }
760
761 Code* code = function->shared()->code();
762 DeoptimizationOutputData* output_data =
763 DeoptimizationOutputData::cast(code->deoptimization_data());
764 unsigned entry = Deoptimizer::GetOutputInfo(output_data,
765 ast_id,
766 function->shared());
767 unsigned pc_offset =
768 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
769 ASSERT(pc_offset > 0);
770
771 FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
772 frames->Add(summary);
773 } else {
774 // Skip over operands to advance to the next opcode.
775 it.Skip(Translation::NumberOfOperandsFor(opcode));
776 }
777 }
778}
779
780
781DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
782 int* deopt_index) {
783 ASSERT(is_optimized());
784
785 JSFunction* opt_function = JSFunction::cast(function());
786 Code* code = opt_function->code();
787
788 // The code object may have been replaced by lazy deoptimization. Fall
789 // back to a slow search in this case to find the original optimized
790 // code object.
791 if (!code->contains(pc())) {
Steve Block44f0eee2011-05-26 01:26:41 +0100792 code = Isolate::Current()->pc_to_code_cache()->GcSafeFindCodeForPc(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100793 }
794 ASSERT(code != NULL);
795 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
796
Ben Murdochb8e0da22011-05-16 14:20:40 +0100797 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
798 *deopt_index = safepoint_entry.deoptimization_index();
Steve Block1e0659c2011-05-24 12:43:12 +0100799 ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100800
801 return DeoptimizationInputData::cast(code->deoptimization_data());
802}
803
804
805void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
806 ASSERT(functions->length() == 0);
807 ASSERT(is_optimized());
808
Steve Block1e0659c2011-05-24 12:43:12 +0100809 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100810 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
811
812 TranslationIterator it(data->TranslationByteArray(),
813 data->TranslationIndex(deopt_index)->value());
814 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
815 ASSERT(opcode == Translation::BEGIN);
816 int frame_count = it.Next();
817
818 // We insert the frames in reverse order because the frames
819 // in the deoptimization translation are ordered bottom-to-top.
820 while (frame_count > 0) {
821 opcode = static_cast<Translation::Opcode>(it.Next());
822 if (opcode == Translation::FRAME) {
823 frame_count--;
824 it.Next(); // Skip ast id.
825 int function_id = it.Next();
826 it.Next(); // Skip height.
827 JSFunction* function =
828 JSFunction::cast(data->LiteralArray()->get(function_id));
829 functions->Add(function);
830 } else {
831 // Skip over operands to advance to the next opcode.
832 it.Skip(Translation::NumberOfOperandsFor(opcode));
833 }
834 }
835}
836
837
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100838Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
839 const int arguments = Smi::cast(GetExpression(0))->value();
840 const int offset = StandardFrameConstants::kCallerSPOffset;
841 return fp() + offset + (arguments + 1) * kPointerSize;
842}
843
844
845Address InternalFrame::GetCallerStackPointer() const {
846 // Internal frames have no arguments. The stack pointer of the
847 // caller is at a fixed offset from the frame pointer.
848 return fp() + StandardFrameConstants::kCallerSPOffset;
849}
850
851
Iain Merrick75681382010-08-19 15:07:18 +0100852Code* ArgumentsAdaptorFrame::unchecked_code() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100853 return Isolate::Current()->builtins()->builtin(
854 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +0000855}
856
857
Iain Merrick75681382010-08-19 15:07:18 +0100858Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000859 const int offset = InternalFrameConstants::kCodeOffset;
860 Object* code = Memory::Object_at(fp() + offset);
861 ASSERT(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +0100862 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000863}
864
865
866void StackFrame::PrintIndex(StringStream* accumulator,
867 PrintMode mode,
868 int index) {
869 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
870}
871
872
873void JavaScriptFrame::Print(StringStream* accumulator,
874 PrintMode mode,
875 int index) const {
876 HandleScope scope;
877 Object* receiver = this->receiver();
878 Object* function = this->function();
879
880 accumulator->PrintSecurityTokenIfChanged(function);
881 PrintIndex(accumulator, mode, index);
882 Code* code = NULL;
883 if (IsConstructor()) accumulator->Add("new ");
884 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +0100885
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100886 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
887
Steve Block6ded16b2010-05-10 14:33:55 +0100888 if (function->IsJSFunction()) {
889 Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100890 scope_info = Handle<SerializedScopeInfo>(shared->scope_info());
Steve Block6ded16b2010-05-10 14:33:55 +0100891 Object* script_obj = shared->script();
892 if (script_obj->IsScript()) {
893 Handle<Script> script(Script::cast(script_obj));
894 accumulator->Add(" [");
895 accumulator->PrintName(script->name());
896
897 Address pc = this->pc();
898 if (code != NULL && code->kind() == Code::FUNCTION &&
Leon Clarkeac952652010-07-15 11:15:24 +0100899 pc >= code->instruction_start() && pc < code->instruction_end()) {
Steve Block6ded16b2010-05-10 14:33:55 +0100900 int source_pos = code->SourcePosition(pc);
901 int line = GetScriptLineNumberSafe(script, source_pos) + 1;
902 accumulator->Add(":%d", line);
903 } else {
904 int function_start_pos = shared->start_position();
905 int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
906 accumulator->Add(":~%d", line);
907 }
908
909 accumulator->Add("] ");
910 }
911 }
912
Steve Blocka7e24c12009-10-30 11:49:00 +0000913 accumulator->Add("(this=%o", receiver);
914
915 // Get scope information for nicer output, if possible. If code is
916 // NULL, or doesn't contain scope info, info will return 0 for the
917 // number of parameters, stack slots, or context slots.
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100918 ScopeInfo<PreallocatedStorage> info(*scope_info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000919
920 // Print the parameters.
921 int parameters_count = ComputeParametersCount();
922 for (int i = 0; i < parameters_count; i++) {
923 accumulator->Add(",");
924 // If we have a name for the parameter we print it. Nameless
925 // parameters are either because we have more actual parameters
926 // than formal parameters or because we have no scope information.
927 if (i < info.number_of_parameters()) {
928 accumulator->PrintName(*info.parameter_name(i));
929 accumulator->Add("=");
930 }
931 accumulator->Add("%o", GetParameter(i));
932 }
933
934 accumulator->Add(")");
935 if (mode == OVERVIEW) {
936 accumulator->Add("\n");
937 return;
938 }
939 accumulator->Add(" {\n");
940
941 // Compute the number of locals and expression stack elements.
942 int stack_locals_count = info.number_of_stack_slots();
943 int heap_locals_count = info.number_of_context_slots();
944 int expressions_count = ComputeExpressionsCount();
945
946 // Print stack-allocated local variables.
947 if (stack_locals_count > 0) {
948 accumulator->Add(" // stack-allocated locals\n");
949 }
950 for (int i = 0; i < stack_locals_count; i++) {
951 accumulator->Add(" var ");
952 accumulator->PrintName(*info.stack_slot_name(i));
953 accumulator->Add(" = ");
954 if (i < expressions_count) {
955 accumulator->Add("%o", GetExpression(i));
956 } else {
957 accumulator->Add("// no expression found - inconsistent frame?");
958 }
959 accumulator->Add("\n");
960 }
961
962 // Try to get hold of the context of this frame.
963 Context* context = NULL;
964 if (this->context() != NULL && this->context()->IsContext()) {
965 context = Context::cast(this->context());
966 }
967
968 // Print heap-allocated local variables.
969 if (heap_locals_count > Context::MIN_CONTEXT_SLOTS) {
970 accumulator->Add(" // heap-allocated locals\n");
971 }
972 for (int i = Context::MIN_CONTEXT_SLOTS; i < heap_locals_count; i++) {
973 accumulator->Add(" var ");
974 accumulator->PrintName(*info.context_slot_name(i));
975 accumulator->Add(" = ");
976 if (context != NULL) {
977 if (i < context->length()) {
978 accumulator->Add("%o", context->get(i));
979 } else {
980 accumulator->Add(
981 "// warning: missing context slot - inconsistent frame?");
982 }
983 } else {
984 accumulator->Add("// warning: no context found - inconsistent frame?");
985 }
986 accumulator->Add("\n");
987 }
988
989 // Print the expression stack.
990 int expressions_start = stack_locals_count;
991 if (expressions_start < expressions_count) {
992 accumulator->Add(" // expression stack (top to bottom)\n");
993 }
994 for (int i = expressions_count - 1; i >= expressions_start; i--) {
995 if (IsExpressionInsideHandler(i)) continue;
996 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
997 }
998
999 // Print details about the function.
1000 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1001 SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
1002 accumulator->Add("--------- s o u r c e c o d e ---------\n");
1003 shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
1004 accumulator->Add("\n-----------------------------------------\n");
1005 }
1006
1007 accumulator->Add("}\n\n");
1008}
1009
1010
1011void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1012 PrintMode mode,
1013 int index) const {
1014 int actual = ComputeParametersCount();
1015 int expected = -1;
1016 Object* function = this->function();
1017 if (function->IsJSFunction()) {
1018 expected = JSFunction::cast(function)->shared()->formal_parameter_count();
1019 }
1020
1021 PrintIndex(accumulator, mode, index);
1022 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1023 if (mode == OVERVIEW) {
1024 accumulator->Add("\n");
1025 return;
1026 }
1027 accumulator->Add(" {\n");
1028
1029 // Print actual arguments.
1030 if (actual > 0) accumulator->Add(" // actual arguments\n");
1031 for (int i = 0; i < actual; i++) {
1032 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1033 if (expected != -1 && i >= expected) {
1034 accumulator->Add(" // not passed to callee");
1035 }
1036 accumulator->Add("\n");
1037 }
1038
1039 accumulator->Add("}\n\n");
1040}
1041
1042
1043void EntryFrame::Iterate(ObjectVisitor* v) const {
1044 StackHandlerIterator it(this, top_handler());
1045 ASSERT(!it.done());
1046 StackHandler* handler = it.handler();
1047 ASSERT(handler->is_entry());
Steve Block44f0eee2011-05-26 01:26:41 +01001048 handler->Iterate(v, LookupCode(Isolate::Current()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001049#ifdef DEBUG
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001050 // Make sure that the entry frame does not contain more than one
1051 // stack handler.
Steve Blocka7e24c12009-10-30 11:49:00 +00001052 it.Advance();
1053 ASSERT(it.done());
1054#endif
Steve Block44f0eee2011-05-26 01:26:41 +01001055 IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001056}
1057
1058
1059void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
1060 const int offset = StandardFrameConstants::kContextOffset;
1061 Object** base = &Memory::Object_at(sp());
1062 Object** limit = &Memory::Object_at(fp() + offset) + 1;
1063 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1064 StackHandler* handler = it.handler();
1065 // Traverse pointers down to - but not including - the next
1066 // handler in the handler chain. Update the base to skip the
1067 // handler and allow the handler to traverse its own pointers.
1068 const Address address = handler->address();
1069 v->VisitPointers(base, reinterpret_cast<Object**>(address));
1070 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1071 // Traverse the pointers in the handler itself.
Steve Block44f0eee2011-05-26 01:26:41 +01001072 handler->Iterate(v, LookupCode(Isolate::Current()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001073 }
1074 v->VisitPointers(base, limit);
1075}
1076
1077
1078void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1079 IterateExpressions(v);
Steve Block44f0eee2011-05-26 01:26:41 +01001080 IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001081 IterateArguments(v);
1082}
Steve Blocka7e24c12009-10-30 11:49:00 +00001083
Ben Murdochb0fe1622011-05-05 13:52:32 +01001084
1085void JavaScriptFrame::IterateArguments(ObjectVisitor* v) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001086 // Traverse callee-saved registers, receiver, and parameters.
1087 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset;
1088 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset;
1089 Object** base = &Memory::Object_at(fp() + kBaseOffset);
1090 Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1;
1091 v->VisitPointers(base, limit);
1092}
1093
1094
1095void InternalFrame::Iterate(ObjectVisitor* v) const {
1096 // Internal frames only have object pointers on the expression stack
1097 // as they never have any arguments.
1098 IterateExpressions(v);
Steve Block44f0eee2011-05-26 01:26:41 +01001099 IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001100}
1101
1102
1103// -------------------------------------------------------------------------
1104
1105
1106JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
1107 ASSERT(n >= 0);
1108 for (int i = 0; i <= n; i++) {
1109 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1110 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1111 iterator_.Advance();
1112 }
1113 UNREACHABLE();
1114 return NULL;
1115}
1116
1117
1118// -------------------------------------------------------------------------
1119
1120
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001121Code* PcToCodeCache::GcSafeCastToCode(HeapObject* object, Address pc) {
1122 Code* code = reinterpret_cast<Code*>(object);
1123 ASSERT(code != NULL && code->contains(pc));
1124 return code;
1125}
1126
1127
1128Code* PcToCodeCache::GcSafeFindCodeForPc(Address pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01001129 Heap* heap = isolate_->heap();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001130 // Check if the pc points into a large object chunk.
Steve Block44f0eee2011-05-26 01:26:41 +01001131 LargeObjectChunk* chunk = heap->lo_space()->FindChunkContainingPc(pc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001132 if (chunk != NULL) return GcSafeCastToCode(chunk->GetObject(), pc);
1133
1134 // Iterate through the 8K page until we reach the end or find an
1135 // object starting after the pc.
1136 Page* page = Page::FromAddress(pc);
Steve Block44f0eee2011-05-26 01:26:41 +01001137 HeapObjectIterator iterator(page, heap->GcSafeSizeOfOldObjectFunction());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001138 HeapObject* previous = NULL;
1139 while (true) {
1140 HeapObject* next = iterator.next();
1141 if (next == NULL || next->address() >= pc) {
1142 return GcSafeCastToCode(previous, pc);
1143 }
1144 previous = next;
1145 }
1146}
1147
Ben Murdochb0fe1622011-05-05 13:52:32 +01001148
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001149PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01001150 isolate_->counters()->pc_to_code()->Increment();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001151 ASSERT(IsPowerOf2(kPcToCodeCacheSize));
1152 uint32_t hash = ComputeIntegerHash(
1153 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc)));
1154 uint32_t index = hash & (kPcToCodeCacheSize - 1);
1155 PcToCodeCacheEntry* entry = cache(index);
1156 if (entry->pc == pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01001157 isolate_->counters()->pc_to_code_cached()->Increment();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001158 ASSERT(entry->code == GcSafeFindCodeForPc(pc));
1159 } else {
1160 // Because this code may be interrupted by a profiling signal that
1161 // also queries the cache, we cannot update pc before the code has
1162 // been set. Otherwise, we risk trying to use a cache entry before
1163 // the code has been computed.
1164 entry->code = GcSafeFindCodeForPc(pc);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001165 entry->safepoint_entry.Reset();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001166 entry->pc = pc;
1167 }
1168 return entry;
1169}
1170
1171
1172// -------------------------------------------------------------------------
1173
Steve Blocka7e24c12009-10-30 11:49:00 +00001174int NumRegs(RegList reglist) {
1175 int n = 0;
1176 while (reglist != 0) {
1177 n++;
1178 reglist &= reglist - 1; // clear one bit
1179 }
1180 return n;
1181}
1182
1183
Steve Block44f0eee2011-05-26 01:26:41 +01001184struct JSCallerSavedCodeData {
1185 JSCallerSavedCodeData() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001186 int i = 0;
1187 for (int r = 0; r < kNumRegs; r++)
1188 if ((kJSCallerSaved & (1 << r)) != 0)
1189 reg_code[i++] = r;
1190
1191 ASSERT(i == kNumJSCallerSaved);
1192 }
Steve Block44f0eee2011-05-26 01:26:41 +01001193 int reg_code[kNumJSCallerSaved];
1194};
1195
1196
1197static const JSCallerSavedCodeData kCallerSavedCodeData;
1198
1199
1200int JSCallerSavedCode(int n) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001201 ASSERT(0 <= n && n < kNumJSCallerSaved);
Steve Block44f0eee2011-05-26 01:26:41 +01001202 return kCallerSavedCodeData.reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001203}
1204
1205
Steve Block6ded16b2010-05-10 14:33:55 +01001206#define DEFINE_WRAPPER(type, field) \
1207class field##_Wrapper : public ZoneObject { \
1208 public: /* NOLINT */ \
1209 field##_Wrapper(const field& original) : frame_(original) { \
1210 } \
1211 field frame_; \
1212};
1213STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1214#undef DEFINE_WRAPPER
1215
1216static StackFrame* AllocateFrameCopy(StackFrame* frame) {
1217#define FRAME_TYPE_CASE(type, field) \
1218 case StackFrame::type: { \
1219 field##_Wrapper* wrapper = \
1220 new field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
1221 return &wrapper->frame_; \
1222 }
1223
1224 switch (frame->type()) {
1225 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1226 default: UNREACHABLE();
1227 }
1228#undef FRAME_TYPE_CASE
1229 return NULL;
1230}
1231
1232Vector<StackFrame*> CreateStackMap() {
1233 ZoneList<StackFrame*> list(10);
1234 for (StackFrameIterator it; !it.done(); it.Advance()) {
1235 StackFrame* frame = AllocateFrameCopy(it.frame());
1236 list.Add(frame);
1237 }
1238 return list.ToVector();
1239}
1240
1241
Steve Blocka7e24c12009-10-30 11:49:00 +00001242} } // namespace v8::internal