blob: 60b1aadfcae073a09bfc7831e436ce3743901bf0 [file] [log] [blame]
Ben Murdoch85b71792012-04-11 18:30:58 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000039#include "allocation-inl.h"
40
Steve Blocka7e24c12009-10-30 11:49:00 +000041namespace v8 {
42namespace internal {
43
44// 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()
Ben Murdoch8b112d22011-06-08 16:22:53 +010075 : isolate_(Isolate::Current()),
76 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
Steve Block44f0eee2011-05-26 01:26:41 +010077 frame_(NULL), handler_(NULL),
Ben Murdoch8b112d22011-06-08 16:22:53 +010078 thread_(isolate_->thread_local_top()),
Steve Blocka7e24c12009-10-30 11:49:00 +000079 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
80 Reset();
81}
Ben Murdoch8b112d22011-06-08 16:22:53 +010082StackFrameIterator::StackFrameIterator(Isolate* isolate)
83 : isolate_(isolate),
84 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
85 frame_(NULL), handler_(NULL),
86 thread_(isolate_->thread_local_top()),
87 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
88 Reset();
89}
90StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
91 : isolate_(isolate),
92 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
Steve Blocka7e24c12009-10-30 11:49:00 +000093 frame_(NULL), handler_(NULL), thread_(t),
94 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
95 Reset();
96}
Steve Block44f0eee2011-05-26 01:26:41 +010097StackFrameIterator::StackFrameIterator(Isolate* isolate,
98 bool use_top, Address fp, Address sp)
Ben Murdoch8b112d22011-06-08 16:22:53 +010099 : isolate_(isolate),
100 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
Steve Blocka7e24c12009-10-30 11:49:00 +0000101 frame_(NULL), handler_(NULL),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100102 thread_(use_top ? isolate_->thread_local_top() : NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 fp_(use_top ? NULL : fp), sp_(sp),
104 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
105 &StackFrameIterator::AdvanceWithoutHandler) {
106 if (use_top || fp != NULL) {
107 Reset();
108 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000109}
110
111#undef INITIALIZE_SINGLETON
112
113
114void StackFrameIterator::AdvanceWithHandler() {
115 ASSERT(!done());
116 // Compute the state of the calling frame before restoring
117 // callee-saved registers and unwinding handlers. This allows the
118 // frame code that computes the caller state to access the top
119 // handler and the value of any callee-saved register if needed.
120 StackFrame::State state;
121 StackFrame::Type type = frame_->GetCallerState(&state);
122
123 // Unwind handlers corresponding to the current frame.
124 StackHandlerIterator it(frame_, handler_);
125 while (!it.done()) it.Advance();
126 handler_ = it.handler();
127
128 // Advance to the calling frame.
129 frame_ = SingletonFor(type, &state);
130
131 // When we're done iterating over the stack frames, the handler
132 // chain must have been completely unwound.
133 ASSERT(!done() || handler_ == NULL);
134}
135
136
137void StackFrameIterator::AdvanceWithoutHandler() {
138 // A simpler version of Advance which doesn't care about handler.
139 ASSERT(!done());
140 StackFrame::State state;
141 StackFrame::Type type = frame_->GetCallerState(&state);
142 frame_ = SingletonFor(type, &state);
143}
144
145
146void StackFrameIterator::Reset() {
147 StackFrame::State state;
148 StackFrame::Type type;
149 if (thread_ != NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100150 type = ExitFrame::GetStateForFramePointer(
151 Isolate::c_entry_fp(thread_), &state);
152 handler_ = StackHandler::FromAddress(
153 Isolate::handler(thread_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000154 } else {
155 ASSERT(fp_ != NULL);
156 state.fp = fp_;
157 state.sp = sp_;
Ben Murdoch85b71792012-04-11 18:30:58 +0100158 state.pc_address =
159 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100160 type = StackFrame::ComputeType(isolate(), &state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000161 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100162 if (SingletonFor(type) == NULL) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000163 frame_ = SingletonFor(type, &state);
164}
165
166
167StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
168 StackFrame::State* state) {
169 if (type == StackFrame::NONE) return NULL;
170 StackFrame* result = SingletonFor(type);
171 ASSERT(result != NULL);
172 result->state_ = *state;
173 return result;
174}
175
176
177StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
178#define FRAME_TYPE_CASE(type, field) \
179 case StackFrame::type: result = &field##_; break;
180
181 StackFrame* result = NULL;
182 switch (type) {
183 case StackFrame::NONE: return NULL;
184 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
185 default: break;
186 }
187 return result;
188
189#undef FRAME_TYPE_CASE
190}
191
192
193// -------------------------------------------------------------------------
194
195
196StackTraceFrameIterator::StackTraceFrameIterator() {
Leon Clarke4515c472010-02-03 11:58:03 +0000197 if (!done() && !IsValidFrame()) Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +0000198}
199
200
Ben Murdoch8b112d22011-06-08 16:22:53 +0100201StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
202 : JavaScriptFrameIterator(isolate) {
203 if (!done() && !IsValidFrame()) Advance();
204}
205
206
Steve Blocka7e24c12009-10-30 11:49:00 +0000207void StackTraceFrameIterator::Advance() {
208 while (true) {
209 JavaScriptFrameIterator::Advance();
210 if (done()) return;
Leon Clarke4515c472010-02-03 11:58:03 +0000211 if (IsValidFrame()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000212 }
213}
214
Leon Clarke4515c472010-02-03 11:58:03 +0000215bool StackTraceFrameIterator::IsValidFrame() {
216 if (!frame()->function()->IsJSFunction()) return false;
217 Object* script = JSFunction::cast(frame()->function())->shared()->script();
218 // Don't show functions from native scripts to user.
219 return (script->IsScript() &&
220 Script::TYPE_NATIVE != Script::cast(script)->type()->value());
221}
222
Steve Blocka7e24c12009-10-30 11:49:00 +0000223
224// -------------------------------------------------------------------------
225
226
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100227bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
228 if (!validator_.IsValid(fp)) return false;
229 Address sp = ExitFrame::ComputeStackPointer(fp);
230 if (!validator_.IsValid(sp)) return false;
231 StackFrame::State state;
232 ExitFrame::FillState(fp, sp, &state);
233 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
234 return false;
235 }
236 return *state.pc_address != NULL;
237}
238
239
Ben Murdoch8b112d22011-06-08 16:22:53 +0100240SafeStackFrameIterator::ActiveCountMaintainer::ActiveCountMaintainer(
241 Isolate* isolate)
242 : isolate_(isolate) {
243 isolate_->set_safe_stack_iterator_counter(
244 isolate_->safe_stack_iterator_counter() + 1);
245}
246
247
248SafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() {
249 isolate_->set_safe_stack_iterator_counter(
250 isolate_->safe_stack_iterator_counter() - 1);
251}
252
253
Steve Blocka7e24c12009-10-30 11:49:00 +0000254SafeStackFrameIterator::SafeStackFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100255 Isolate* isolate,
Steve Blocka7e24c12009-10-30 11:49:00 +0000256 Address fp, Address sp, Address low_bound, Address high_bound) :
Ben Murdoch8b112d22011-06-08 16:22:53 +0100257 maintainer_(isolate),
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100258 stack_validator_(low_bound, high_bound),
Steve Block44f0eee2011-05-26 01:26:41 +0100259 is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
Steve Blocka7e24c12009-10-30 11:49:00 +0000260 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
261 is_working_iterator_(is_valid_top_ || is_valid_fp_),
262 iteration_done_(!is_working_iterator_),
Steve Block44f0eee2011-05-26 01:26:41 +0100263 iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000264}
265
Ben Murdoch8b112d22011-06-08 16:22:53 +0100266bool SafeStackFrameIterator::is_active(Isolate* isolate) {
267 return isolate->safe_stack_iterator_counter() > 0;
268}
269
Steve Blocka7e24c12009-10-30 11:49:00 +0000270
Steve Block44f0eee2011-05-26 01:26:41 +0100271bool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
272 Address low_bound, Address high_bound) {
273 ThreadLocalTop* top = isolate->thread_local_top();
274 Address fp = Isolate::c_entry_fp(top);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100275 ExitFrameValidator validator(low_bound, high_bound);
276 if (!validator.IsValidFP(fp)) return false;
Steve Block44f0eee2011-05-26 01:26:41 +0100277 return Isolate::handler(top) != NULL;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100278}
279
280
Steve Blocka7e24c12009-10-30 11:49:00 +0000281void SafeStackFrameIterator::Advance() {
282 ASSERT(is_working_iterator_);
283 ASSERT(!done());
284 StackFrame* last_frame = iterator_.frame();
285 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
286 // Before advancing to the next stack frame, perform pointer validity tests
287 iteration_done_ = !IsValidFrame(last_frame) ||
288 !CanIterateHandles(last_frame, iterator_.handler()) ||
289 !IsValidCaller(last_frame);
290 if (iteration_done_) return;
291
292 iterator_.Advance();
293 if (iterator_.done()) return;
294 // Check that we have actually moved to the previous frame in the stack
295 StackFrame* prev_frame = iterator_.frame();
296 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
297}
298
299
300bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
301 StackHandler* handler) {
302 // If StackIterator iterates over StackHandles, verify that
303 // StackHandlerIterator can be instantiated (see StackHandlerIterator
304 // constructor.)
305 return !is_valid_top_ || (frame->sp() <= handler->address());
306}
307
308
309bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
310 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
311}
312
313
314bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
315 StackFrame::State state;
316 if (frame->is_entry() || frame->is_entry_construct()) {
317 // See EntryFrame::GetCallerState. It computes the caller FP address
318 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
319 // sure that caller FP address is valid.
320 Address caller_fp = Memory::Address_at(
321 frame->fp() + EntryFrameConstants::kCallerFPOffset);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100322 ExitFrameValidator validator(stack_validator_);
323 if (!validator.IsValidFP(caller_fp)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000324 } else if (frame->is_arguments_adaptor()) {
325 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
326 // the number of arguments is stored on stack as Smi. We need to check
327 // that it really an Smi.
328 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
329 GetExpression(0);
330 if (!number_of_args->IsSmi()) {
331 return false;
332 }
333 }
334 frame->ComputeCallerState(&state);
335 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
336 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
337}
338
339
340void SafeStackFrameIterator::Reset() {
341 if (is_working_iterator_) {
342 iterator_.Reset();
343 iteration_done_ = false;
344 }
345}
346
347
348// -------------------------------------------------------------------------
349
350
Steve Blocka7e24c12009-10-30 11:49:00 +0000351SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100352 Isolate* isolate,
Steve Blocka7e24c12009-10-30 11:49:00 +0000353 Address fp, Address sp, Address low_bound, Address high_bound) :
Steve Block44f0eee2011-05-26 01:26:41 +0100354 SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 if (!done() && !frame()->is_java_script()) Advance();
356}
357
358
359void SafeStackTraceFrameIterator::Advance() {
360 while (true) {
361 SafeJavaScriptFrameIterator::Advance();
362 if (done()) return;
363 if (frame()->is_java_script()) return;
364 }
365}
Steve Blocka7e24c12009-10-30 11:49:00 +0000366
367
Ben Murdoch8b112d22011-06-08 16:22:53 +0100368Code* StackFrame::GetSafepointData(Isolate* isolate,
Ben Murdoch85b71792012-04-11 18:30:58 +0100369 Address pc,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100370 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100371 unsigned* stack_slots) {
Ben Murdoch85b71792012-04-11 18:30:58 +0100372 PcToCodeCache::PcToCodeCacheEntry* entry =
373 isolate->pc_to_code_cache()->GetCacheEntry(pc);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100374 if (!entry->safepoint_entry.is_valid()) {
Ben Murdoch85b71792012-04-11 18:30:58 +0100375 entry->safepoint_entry = entry->code->GetSafepointEntry(pc);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100376 ASSERT(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100377 } else {
Ben Murdoch85b71792012-04-11 18:30:58 +0100378 ASSERT(entry->safepoint_entry.Equals(entry->code->GetSafepointEntry(pc)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100379 }
380
381 // Fill in the results and return the code.
382 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100383 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100384 *stack_slots = code->stack_slots();
385 return code;
386}
387
388
Steve Blocka7e24c12009-10-30 11:49:00 +0000389bool StackFrame::HasHandler() const {
390 StackHandlerIterator it(this, top_handler());
391 return !it.done();
392}
393
Ben Murdochb0fe1622011-05-05 13:52:32 +0100394
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100395void StackFrame::IteratePc(ObjectVisitor* v,
396 Address* pc_address,
397 Code* holder) {
398 Address pc = *pc_address;
Ben Murdoch85b71792012-04-11 18:30:58 +0100399 ASSERT(holder->contains(pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100400 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
401 Object* code = holder;
402 v->VisitPointer(&code);
403 if (code != holder) {
404 holder = reinterpret_cast<Code*>(code);
405 pc = holder->instruction_start() + pc_offset;
406 *pc_address = pc;
Steve Blocka7e24c12009-10-30 11:49:00 +0000407 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000408}
409
410
Ben Murdoch8b112d22011-06-08 16:22:53 +0100411StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100412 ASSERT(state->fp != NULL);
413 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
414 return ARGUMENTS_ADAPTOR;
Steve Blocka7e24c12009-10-30 11:49:00 +0000415 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100416 // The marker and function offsets overlap. If the marker isn't a
417 // smi then the frame is a JavaScript frame -- and the marker is
418 // really the function.
419 const int offset = StandardFrameConstants::kMarkerOffset;
420 Object* marker = Memory::Object_at(state->fp + offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100421 if (!marker->IsSmi()) {
422 // If we're using a "safe" stack iterator, we treat optimized
423 // frames as normal JavaScript frames to avoid having to look
424 // into the heap to determine the state. This is safe as long
425 // as nobody tries to GC...
Ben Murdoch8b112d22011-06-08 16:22:53 +0100426 if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT;
427 Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100428 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
429 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
430 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100431 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000432}
433
434
Steve Blocka7e24c12009-10-30 11:49:00 +0000435
436StackFrame::Type StackFrame::GetCallerState(State* state) const {
437 ComputeCallerState(state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100438 return ComputeType(isolate(), state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000439}
440
441
Iain Merrick75681382010-08-19 15:07:18 +0100442Code* EntryFrame::unchecked_code() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100443 return HEAP->raw_unchecked_js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000444}
445
446
447void EntryFrame::ComputeCallerState(State* state) const {
448 GetCallerState(state);
449}
450
451
Steve Block6ded16b2010-05-10 14:33:55 +0100452void EntryFrame::SetCallerFp(Address caller_fp) {
453 const int offset = EntryFrameConstants::kCallerFPOffset;
454 Memory::Address_at(this->fp() + offset) = caller_fp;
455}
456
457
Steve Blocka7e24c12009-10-30 11:49:00 +0000458StackFrame::Type EntryFrame::GetCallerState(State* state) const {
459 const int offset = EntryFrameConstants::kCallerFPOffset;
460 Address fp = Memory::Address_at(this->fp() + offset);
461 return ExitFrame::GetStateForFramePointer(fp, state);
462}
463
464
Iain Merrick75681382010-08-19 15:07:18 +0100465Code* EntryConstructFrame::unchecked_code() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100466 return HEAP->raw_unchecked_js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000467}
468
469
Steve Blockd0582a62009-12-15 09:54:21 +0000470Object*& ExitFrame::code_slot() const {
471 const int offset = ExitFrameConstants::kCodeOffset;
472 return Memory::Object_at(fp() + offset);
473}
474
475
Iain Merrick75681382010-08-19 15:07:18 +0100476Code* ExitFrame::unchecked_code() const {
477 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000478}
479
480
481void ExitFrame::ComputeCallerState(State* state) const {
Ben Murdoch85b71792012-04-11 18:30:58 +0100482 // Setup the caller state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 state->sp = caller_sp();
484 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
Ben Murdoch85b71792012-04-11 18:30:58 +0100485 state->pc_address
486 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +0000487}
488
489
Steve Block6ded16b2010-05-10 14:33:55 +0100490void ExitFrame::SetCallerFp(Address caller_fp) {
491 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
492}
493
494
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100495void ExitFrame::Iterate(ObjectVisitor* v) const {
496 // The arguments are traversed as part of the expression stack of
497 // the calling frame.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100498 IteratePc(v, pc_address(), LookupCode());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100499 v->VisitPointer(&code_slot());
500}
501
502
Steve Blocka7e24c12009-10-30 11:49:00 +0000503Address ExitFrame::GetCallerStackPointer() const {
504 return fp() + ExitFrameConstants::kCallerSPDisplacement;
505}
506
507
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100508StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
509 if (fp == 0) return NONE;
510 Address sp = ComputeStackPointer(fp);
511 FillState(fp, sp, state);
512 ASSERT(*state->pc_address != NULL);
513 return EXIT;
514}
515
516
517void ExitFrame::FillState(Address fp, Address sp, State* state) {
518 state->sp = sp;
519 state->fp = fp;
Ben Murdoch85b71792012-04-11 18:30:58 +0100520 state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100521}
522
523
Steve Blocka7e24c12009-10-30 11:49:00 +0000524Address StandardFrame::GetExpressionAddress(int n) const {
525 const int offset = StandardFrameConstants::kExpressionsOffset;
526 return fp() + offset - n * kPointerSize;
527}
528
529
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000530Object* StandardFrame::GetExpression(Address fp, int index) {
531 return Memory::Object_at(GetExpressionAddress(fp, index));
532}
533
534
535Address StandardFrame::GetExpressionAddress(Address fp, int n) {
536 const int offset = StandardFrameConstants::kExpressionsOffset;
537 return fp + offset - n * kPointerSize;
538}
539
540
Steve Blocka7e24c12009-10-30 11:49:00 +0000541int StandardFrame::ComputeExpressionsCount() const {
542 const int offset =
543 StandardFrameConstants::kExpressionsOffset + kPointerSize;
544 Address base = fp() + offset;
545 Address limit = sp();
546 ASSERT(base >= limit); // stack grows downwards
547 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000548 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000549}
550
551
552void StandardFrame::ComputeCallerState(State* state) const {
553 state->sp = caller_sp();
554 state->fp = caller_fp();
Ben Murdoch85b71792012-04-11 18:30:58 +0100555 state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000556}
557
558
Steve Block6ded16b2010-05-10 14:33:55 +0100559void StandardFrame::SetCallerFp(Address caller_fp) {
560 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
561 caller_fp;
562}
563
564
Steve Blocka7e24c12009-10-30 11:49:00 +0000565bool StandardFrame::IsExpressionInsideHandler(int n) const {
566 Address address = GetExpressionAddress(n);
567 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
568 if (it.handler()->includes(address)) return true;
569 }
570 return false;
571}
572
573
Ben Murdochb0fe1622011-05-05 13:52:32 +0100574void OptimizedFrame::Iterate(ObjectVisitor* v) const {
575#ifdef DEBUG
576 // Make sure that optimized frames do not contain any stack handlers.
577 StackHandlerIterator it(this, top_handler());
578 ASSERT(it.done());
579#endif
580
581 // Make sure that we're not doing "safe" stack frame iteration. We cannot
582 // possibly find pointers in optimized frames in that state.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100583 ASSERT(!SafeStackFrameIterator::is_active(isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100584
585 // Compute the safepoint information.
586 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100587 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100588 Code* code = StackFrame::GetSafepointData(
Ben Murdoch8b112d22011-06-08 16:22:53 +0100589 isolate(), pc(), &safepoint_entry, &stack_slots);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100590 unsigned slot_space = stack_slots * kPointerSize;
591
Ben Murdoch8b112d22011-06-08 16:22:53 +0100592 // Visit the outgoing parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100593 Object** parameters_base = &Memory::Object_at(sp());
594 Object** parameters_limit = &Memory::Object_at(
595 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
596
Ben Murdochb8e0da22011-05-16 14:20:40 +0100597 // Visit the parameters that may be on top of the saved registers.
598 if (safepoint_entry.argument_count() > 0) {
599 v->VisitPointers(parameters_base,
600 parameters_base + safepoint_entry.argument_count());
601 parameters_base += safepoint_entry.argument_count();
602 }
603
604 // Skip saved double registers.
605 if (safepoint_entry.has_doubles()) {
606 parameters_base += DoubleRegister::kNumAllocatableRegisters *
607 kDoubleSize / kPointerSize;
608 }
609
Ben Murdochb0fe1622011-05-05 13:52:32 +0100610 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100611 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100612 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100613 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100614 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
615 v->VisitPointer(parameters_base + reg_stack_index);
616 }
617 }
618 // Skip the words containing the register values.
619 parameters_base += kNumSafepointRegisters;
620 }
621
622 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100623 uint8_t* safepoint_bits = safepoint_entry.bits();
624 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100625
626 // Visit the rest of the parameters.
627 v->VisitPointers(parameters_base, parameters_limit);
628
629 // Visit pointer spill slots and locals.
630 for (unsigned index = 0; index < stack_slots; index++) {
631 int byte_index = index >> kBitsPerByteLog2;
632 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100633 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100634 v->VisitPointer(parameters_limit + index);
635 }
636 }
637
638 // Visit the context and the function.
639 Object** fixed_base = &Memory::Object_at(
640 fp() + JavaScriptFrameConstants::kFunctionOffset);
641 Object** fixed_limit = &Memory::Object_at(fp());
642 v->VisitPointers(fixed_base, fixed_limit);
643
644 // Visit the return address in the callee and incoming arguments.
645 IteratePc(v, pc_address(), code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000646}
647
648
649bool JavaScriptFrame::IsConstructor() const {
650 Address fp = caller_fp();
651 if (has_adapted_arguments()) {
652 // Skip the arguments adaptor frame and look at the real caller.
653 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
654 }
655 return IsConstructFrame(fp);
656}
657
658
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000659int JavaScriptFrame::GetArgumentsLength() const {
660 // If there is an arguments adaptor frame get the arguments length from it.
661 if (has_adapted_arguments()) {
662 return Smi::cast(GetExpression(caller_fp(), 0))->value();
663 } else {
664 return GetNumberOfIncomingArguments();
665 }
666}
667
668
Iain Merrick75681382010-08-19 15:07:18 +0100669Code* JavaScriptFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000670 JSFunction* function = JSFunction::cast(this->function());
Iain Merrick75681382010-08-19 15:07:18 +0100671 return function->unchecked_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000672}
673
674
Ben Murdoch8b112d22011-06-08 16:22:53 +0100675int JavaScriptFrame::GetNumberOfIncomingArguments() const {
676 ASSERT(!SafeStackFrameIterator::is_active(isolate()) &&
677 isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
678
679 JSFunction* function = JSFunction::cast(this->function());
680 return function->shared()->formal_parameter_count();
681}
682
683
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100684Address JavaScriptFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100685 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100686}
687
688
Ben Murdochb0fe1622011-05-05 13:52:32 +0100689void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
690 ASSERT(functions->length() == 0);
691 functions->Add(JSFunction::cast(function()));
692}
693
694
695void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
696 ASSERT(functions->length() == 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100697 Code* code_pointer = LookupCode();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100698 int offset = static_cast<int>(pc() - code_pointer->address());
699 FrameSummary summary(receiver(),
700 JSFunction::cast(function()),
701 code_pointer,
702 offset,
703 IsConstructor());
704 functions->Add(summary);
705}
706
707
708void FrameSummary::Print() {
709 PrintF("receiver: ");
710 receiver_->ShortPrint();
711 PrintF("\nfunction: ");
712 function_->shared()->DebugName()->ShortPrint();
713 PrintF("\ncode: ");
714 code_->ShortPrint();
715 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
716 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
717 PrintF("\npc: %d\n", offset_);
718}
719
720
721void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
722 ASSERT(frames->length() == 0);
723 ASSERT(is_optimized());
724
Steve Block1e0659c2011-05-24 12:43:12 +0100725 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100726 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
727
728 // BUG(3243555): Since we don't have a lazy-deopt registered at
729 // throw-statements, we can't use the translation at the call-site of
730 // throw. An entry with no deoptimization index indicates a call-site
731 // without a lazy-deopt. As a consequence we are not allowed to inline
732 // functions containing throw.
733 if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
734 JavaScriptFrame::Summarize(frames);
735 return;
736 }
737
738 TranslationIterator it(data->TranslationByteArray(),
739 data->TranslationIndex(deopt_index)->value());
740 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
741 ASSERT(opcode == Translation::BEGIN);
Ben Murdoch85b71792012-04-11 18:30:58 +0100742 int frame_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100743
744 // We create the summary in reverse order because the frames
745 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch85b71792012-04-11 18:30:58 +0100746 int i = frame_count;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100747 while (i > 0) {
748 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch85b71792012-04-11 18:30:58 +0100749 if (opcode == Translation::FRAME) {
750 // We don't inline constructor calls, so only the first, outermost
751 // frame can be a constructor frame in case of inlining.
752 bool is_constructor = (i == frame_count) && IsConstructor();
753
Ben Murdochb0fe1622011-05-05 13:52:32 +0100754 i--;
755 int ast_id = it.Next();
756 int function_id = it.Next();
757 it.Next(); // Skip height.
758 JSFunction* function =
759 JSFunction::cast(data->LiteralArray()->get(function_id));
760
761 // The translation commands are ordered and the receiver is always
762 // at the first position. Since we are always at a call when we need
763 // to construct a stack trace, the receiver is always in a stack slot.
764 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch257744e2011-11-30 15:57:28 +0000765 ASSERT(opcode == Translation::STACK_SLOT ||
766 opcode == Translation::LITERAL);
767 int index = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100768
769 // Get the correct receiver in the optimized frame.
770 Object* receiver = NULL;
Ben Murdoch257744e2011-11-30 15:57:28 +0000771 if (opcode == Translation::LITERAL) {
772 receiver = data->LiteralArray()->get(index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100773 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +0000774 // Positive index means the value is spilled to the locals
775 // area. Negative means it is stored in the incoming parameter
776 // area.
777 if (index >= 0) {
778 receiver = GetExpression(index);
779 } else {
780 // Index -1 overlaps with last parameter, -n with the first parameter,
781 // (-n - 1) with the receiver with n being the number of parameters
782 // of the outermost, optimized frame.
783 int parameter_count = ComputeParametersCount();
784 int parameter_index = index + parameter_count;
785 receiver = (parameter_index == -1)
786 ? this->receiver()
787 : this->GetParameter(parameter_index);
788 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100789 }
790
791 Code* code = function->shared()->code();
792 DeoptimizationOutputData* output_data =
793 DeoptimizationOutputData::cast(code->deoptimization_data());
794 unsigned entry = Deoptimizer::GetOutputInfo(output_data,
795 ast_id,
796 function->shared());
797 unsigned pc_offset =
798 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
799 ASSERT(pc_offset > 0);
800
801 FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
802 frames->Add(summary);
803 } else {
804 // Skip over operands to advance to the next opcode.
805 it.Skip(Translation::NumberOfOperandsFor(opcode));
806 }
807 }
808}
809
810
811DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
812 int* deopt_index) {
813 ASSERT(is_optimized());
814
815 JSFunction* opt_function = JSFunction::cast(function());
816 Code* code = opt_function->code();
817
818 // The code object may have been replaced by lazy deoptimization. Fall
819 // back to a slow search in this case to find the original optimized
820 // code object.
821 if (!code->contains(pc())) {
Ben Murdoch85b71792012-04-11 18:30:58 +0100822 code = isolate()->pc_to_code_cache()->GcSafeFindCodeForPc(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100823 }
824 ASSERT(code != NULL);
825 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
826
Ben Murdochb8e0da22011-05-16 14:20:40 +0100827 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
828 *deopt_index = safepoint_entry.deoptimization_index();
Steve Block1e0659c2011-05-24 12:43:12 +0100829 ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100830
831 return DeoptimizationInputData::cast(code->deoptimization_data());
832}
833
834
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000835int OptimizedFrame::GetInlineCount() {
836 ASSERT(is_optimized());
837
838 int deopt_index = Safepoint::kNoDeoptimizationIndex;
839 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
840
841 TranslationIterator it(data->TranslationByteArray(),
842 data->TranslationIndex(deopt_index)->value());
843 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
844 ASSERT(opcode == Translation::BEGIN);
845 USE(opcode);
Ben Murdoch85b71792012-04-11 18:30:58 +0100846 int frame_count = it.Next();
847 return frame_count;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000848}
849
850
Ben Murdochb0fe1622011-05-05 13:52:32 +0100851void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
852 ASSERT(functions->length() == 0);
853 ASSERT(is_optimized());
854
Steve Block1e0659c2011-05-24 12:43:12 +0100855 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100856 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
857
858 TranslationIterator it(data->TranslationByteArray(),
859 data->TranslationIndex(deopt_index)->value());
860 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
861 ASSERT(opcode == Translation::BEGIN);
Ben Murdoch85b71792012-04-11 18:30:58 +0100862 int frame_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100863
864 // We insert the frames in reverse order because the frames
865 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch85b71792012-04-11 18:30:58 +0100866 while (frame_count > 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100867 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch85b71792012-04-11 18:30:58 +0100868 if (opcode == Translation::FRAME) {
869 frame_count--;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100870 it.Next(); // Skip ast id.
871 int function_id = it.Next();
872 it.Next(); // Skip height.
873 JSFunction* function =
874 JSFunction::cast(data->LiteralArray()->get(function_id));
875 functions->Add(function);
876 } else {
877 // Skip over operands to advance to the next opcode.
878 it.Skip(Translation::NumberOfOperandsFor(opcode));
879 }
880 }
881}
882
883
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100884Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100885 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100886}
887
888
889Address InternalFrame::GetCallerStackPointer() const {
890 // Internal frames have no arguments. The stack pointer of the
891 // caller is at a fixed offset from the frame pointer.
892 return fp() + StandardFrameConstants::kCallerSPOffset;
893}
894
895
Iain Merrick75681382010-08-19 15:07:18 +0100896Code* ArgumentsAdaptorFrame::unchecked_code() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100897 return isolate()->builtins()->builtin(
Steve Block44f0eee2011-05-26 01:26:41 +0100898 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +0000899}
900
901
Iain Merrick75681382010-08-19 15:07:18 +0100902Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000903 const int offset = InternalFrameConstants::kCodeOffset;
904 Object* code = Memory::Object_at(fp() + offset);
905 ASSERT(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +0100906 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000907}
908
909
910void StackFrame::PrintIndex(StringStream* accumulator,
911 PrintMode mode,
912 int index) {
913 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
914}
915
916
917void JavaScriptFrame::Print(StringStream* accumulator,
918 PrintMode mode,
919 int index) const {
920 HandleScope scope;
921 Object* receiver = this->receiver();
922 Object* function = this->function();
923
924 accumulator->PrintSecurityTokenIfChanged(function);
925 PrintIndex(accumulator, mode, index);
926 Code* code = NULL;
927 if (IsConstructor()) accumulator->Add("new ");
928 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +0100929
Ben Murdoch85b71792012-04-11 18:30:58 +0100930 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100931
Steve Block6ded16b2010-05-10 14:33:55 +0100932 if (function->IsJSFunction()) {
933 Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
Ben Murdoch85b71792012-04-11 18:30:58 +0100934 scope_info = Handle<SerializedScopeInfo>(shared->scope_info());
Steve Block6ded16b2010-05-10 14:33:55 +0100935 Object* script_obj = shared->script();
936 if (script_obj->IsScript()) {
937 Handle<Script> script(Script::cast(script_obj));
938 accumulator->Add(" [");
939 accumulator->PrintName(script->name());
940
941 Address pc = this->pc();
942 if (code != NULL && code->kind() == Code::FUNCTION &&
Leon Clarkeac952652010-07-15 11:15:24 +0100943 pc >= code->instruction_start() && pc < code->instruction_end()) {
Steve Block6ded16b2010-05-10 14:33:55 +0100944 int source_pos = code->SourcePosition(pc);
945 int line = GetScriptLineNumberSafe(script, source_pos) + 1;
946 accumulator->Add(":%d", line);
947 } else {
948 int function_start_pos = shared->start_position();
949 int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
950 accumulator->Add(":~%d", line);
951 }
952
953 accumulator->Add("] ");
954 }
955 }
956
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 accumulator->Add("(this=%o", receiver);
958
Ben Murdoch85b71792012-04-11 18:30:58 +0100959 // Get scope information for nicer output, if possible. If code is
960 // NULL, or doesn't contain scope info, info will return 0 for the
961 // number of parameters, stack slots, or context slots.
962 ScopeInfo<PreallocatedStorage> info(*scope_info);
963
Steve Blocka7e24c12009-10-30 11:49:00 +0000964 // Print the parameters.
965 int parameters_count = ComputeParametersCount();
966 for (int i = 0; i < parameters_count; i++) {
967 accumulator->Add(",");
968 // If we have a name for the parameter we print it. Nameless
969 // parameters are either because we have more actual parameters
970 // than formal parameters or because we have no scope information.
Ben Murdoch85b71792012-04-11 18:30:58 +0100971 if (i < info.number_of_parameters()) {
972 accumulator->PrintName(*info.parameter_name(i));
Steve Blocka7e24c12009-10-30 11:49:00 +0000973 accumulator->Add("=");
974 }
975 accumulator->Add("%o", GetParameter(i));
976 }
977
978 accumulator->Add(")");
979 if (mode == OVERVIEW) {
980 accumulator->Add("\n");
981 return;
982 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000983 if (is_optimized()) {
984 accumulator->Add(" {\n// optimized frame\n}\n");
985 return;
986 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000987 accumulator->Add(" {\n");
988
989 // Compute the number of locals and expression stack elements.
Ben Murdoch85b71792012-04-11 18:30:58 +0100990 int stack_locals_count = info.number_of_stack_slots();
991 int heap_locals_count = info.number_of_context_slots();
Steve Blocka7e24c12009-10-30 11:49:00 +0000992 int expressions_count = ComputeExpressionsCount();
993
994 // Print stack-allocated local variables.
995 if (stack_locals_count > 0) {
996 accumulator->Add(" // stack-allocated locals\n");
997 }
998 for (int i = 0; i < stack_locals_count; i++) {
999 accumulator->Add(" var ");
Ben Murdoch85b71792012-04-11 18:30:58 +01001000 accumulator->PrintName(*info.stack_slot_name(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001001 accumulator->Add(" = ");
1002 if (i < expressions_count) {
1003 accumulator->Add("%o", GetExpression(i));
1004 } else {
1005 accumulator->Add("// no expression found - inconsistent frame?");
1006 }
1007 accumulator->Add("\n");
1008 }
1009
1010 // Try to get hold of the context of this frame.
1011 Context* context = NULL;
1012 if (this->context() != NULL && this->context()->IsContext()) {
1013 context = Context::cast(this->context());
1014 }
1015
1016 // Print heap-allocated local variables.
Ben Murdoch85b71792012-04-11 18:30:58 +01001017 if (heap_locals_count > Context::MIN_CONTEXT_SLOTS) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001018 accumulator->Add(" // heap-allocated locals\n");
1019 }
Ben Murdoch85b71792012-04-11 18:30:58 +01001020 for (int i = Context::MIN_CONTEXT_SLOTS; i < heap_locals_count; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001021 accumulator->Add(" var ");
Ben Murdoch85b71792012-04-11 18:30:58 +01001022 accumulator->PrintName(*info.context_slot_name(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001023 accumulator->Add(" = ");
1024 if (context != NULL) {
1025 if (i < context->length()) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001026 accumulator->Add("%o", context->get(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001027 } else {
1028 accumulator->Add(
1029 "// warning: missing context slot - inconsistent frame?");
1030 }
1031 } else {
1032 accumulator->Add("// warning: no context found - inconsistent frame?");
1033 }
1034 accumulator->Add("\n");
1035 }
1036
1037 // Print the expression stack.
1038 int expressions_start = stack_locals_count;
1039 if (expressions_start < expressions_count) {
1040 accumulator->Add(" // expression stack (top to bottom)\n");
1041 }
1042 for (int i = expressions_count - 1; i >= expressions_start; i--) {
1043 if (IsExpressionInsideHandler(i)) continue;
1044 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1045 }
1046
1047 // Print details about the function.
1048 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1049 SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
1050 accumulator->Add("--------- s o u r c e c o d e ---------\n");
1051 shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
1052 accumulator->Add("\n-----------------------------------------\n");
1053 }
1054
1055 accumulator->Add("}\n\n");
1056}
1057
1058
1059void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1060 PrintMode mode,
1061 int index) const {
1062 int actual = ComputeParametersCount();
1063 int expected = -1;
1064 Object* function = this->function();
1065 if (function->IsJSFunction()) {
1066 expected = JSFunction::cast(function)->shared()->formal_parameter_count();
1067 }
1068
1069 PrintIndex(accumulator, mode, index);
1070 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1071 if (mode == OVERVIEW) {
1072 accumulator->Add("\n");
1073 return;
1074 }
1075 accumulator->Add(" {\n");
1076
1077 // Print actual arguments.
1078 if (actual > 0) accumulator->Add(" // actual arguments\n");
1079 for (int i = 0; i < actual; i++) {
1080 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1081 if (expected != -1 && i >= expected) {
1082 accumulator->Add(" // not passed to callee");
1083 }
1084 accumulator->Add("\n");
1085 }
1086
1087 accumulator->Add("}\n\n");
1088}
1089
1090
1091void EntryFrame::Iterate(ObjectVisitor* v) const {
1092 StackHandlerIterator it(this, top_handler());
1093 ASSERT(!it.done());
1094 StackHandler* handler = it.handler();
Ben Murdoch85b71792012-04-11 18:30:58 +01001095 ASSERT(handler->is_entry());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001096 handler->Iterate(v, LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001097#ifdef DEBUG
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001098 // Make sure that the entry frame does not contain more than one
1099 // stack handler.
Steve Blocka7e24c12009-10-30 11:49:00 +00001100 it.Advance();
1101 ASSERT(it.done());
1102#endif
Ben Murdoch8b112d22011-06-08 16:22:53 +01001103 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001104}
1105
1106
1107void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
1108 const int offset = StandardFrameConstants::kContextOffset;
1109 Object** base = &Memory::Object_at(sp());
1110 Object** limit = &Memory::Object_at(fp() + offset) + 1;
1111 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1112 StackHandler* handler = it.handler();
1113 // Traverse pointers down to - but not including - the next
1114 // handler in the handler chain. Update the base to skip the
1115 // handler and allow the handler to traverse its own pointers.
1116 const Address address = handler->address();
1117 v->VisitPointers(base, reinterpret_cast<Object**>(address));
1118 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1119 // Traverse the pointers in the handler itself.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001120 handler->Iterate(v, LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001121 }
1122 v->VisitPointers(base, limit);
1123}
1124
1125
1126void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1127 IterateExpressions(v);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001128 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001129}
1130
1131
1132void InternalFrame::Iterate(ObjectVisitor* v) const {
1133 // Internal frames only have object pointers on the expression stack
1134 // as they never have any arguments.
1135 IterateExpressions(v);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001136 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001137}
1138
1139
1140// -------------------------------------------------------------------------
1141
1142
1143JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
1144 ASSERT(n >= 0);
1145 for (int i = 0; i <= n; i++) {
1146 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1147 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1148 iterator_.Advance();
1149 }
1150 UNREACHABLE();
1151 return NULL;
1152}
1153
1154
1155// -------------------------------------------------------------------------
1156
1157
Ben Murdoch85b71792012-04-11 18:30:58 +01001158Code* PcToCodeCache::GcSafeCastToCode(HeapObject* object, Address pc) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001159 Code* code = reinterpret_cast<Code*>(object);
Ben Murdoch85b71792012-04-11 18:30:58 +01001160 ASSERT(code != NULL && code->contains(pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001161 return code;
1162}
1163
1164
Ben Murdoch85b71792012-04-11 18:30:58 +01001165Code* PcToCodeCache::GcSafeFindCodeForPc(Address pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01001166 Heap* heap = isolate_->heap();
Ben Murdoch85b71792012-04-11 18:30:58 +01001167 // Check if the pc points into a large object chunk.
1168 LargeObjectChunk* chunk = heap->lo_space()->FindChunkContainingPc(pc);
1169 if (chunk != NULL) return GcSafeCastToCode(chunk->GetObject(), pc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001170
Ben Murdoch85b71792012-04-11 18:30:58 +01001171 // Iterate through the 8K page until we reach the end or find an
1172 // object starting after the pc.
1173 Page* page = Page::FromAddress(pc);
1174 HeapObjectIterator iterator(page, heap->GcSafeSizeOfOldObjectFunction());
1175 HeapObject* previous = NULL;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001176 while (true) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001177 HeapObject* next = iterator.next();
1178 if (next == NULL || next->address() >= pc) {
1179 return GcSafeCastToCode(previous, pc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001180 }
Ben Murdoch85b71792012-04-11 18:30:58 +01001181 previous = next;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001182 }
1183}
1184
Ben Murdochb0fe1622011-05-05 13:52:32 +01001185
Ben Murdoch85b71792012-04-11 18:30:58 +01001186PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01001187 isolate_->counters()->pc_to_code()->Increment();
Ben Murdoch85b71792012-04-11 18:30:58 +01001188 ASSERT(IsPowerOf2(kPcToCodeCacheSize));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001189 uint32_t hash = ComputeIntegerHash(
Ben Murdoch85b71792012-04-11 18:30:58 +01001190 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc)),
Ben Murdochc7cc0282012-03-05 14:35:55 +00001191 v8::internal::kZeroHashSeed);
Ben Murdoch85b71792012-04-11 18:30:58 +01001192 uint32_t index = hash & (kPcToCodeCacheSize - 1);
1193 PcToCodeCacheEntry* entry = cache(index);
1194 if (entry->pc == pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01001195 isolate_->counters()->pc_to_code_cached()->Increment();
Ben Murdoch85b71792012-04-11 18:30:58 +01001196 ASSERT(entry->code == GcSafeFindCodeForPc(pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001197 } else {
1198 // Because this code may be interrupted by a profiling signal that
Ben Murdoch85b71792012-04-11 18:30:58 +01001199 // also queries the cache, we cannot update pc before the code has
1200 // been set. Otherwise, we risk trying to use a cache entry before
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001201 // the code has been computed.
Ben Murdoch85b71792012-04-11 18:30:58 +01001202 entry->code = GcSafeFindCodeForPc(pc);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001203 entry->safepoint_entry.Reset();
Ben Murdoch85b71792012-04-11 18:30:58 +01001204 entry->pc = pc;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001205 }
1206 return entry;
1207}
1208
1209
1210// -------------------------------------------------------------------------
1211
Steve Blocka7e24c12009-10-30 11:49:00 +00001212int NumRegs(RegList reglist) {
1213 int n = 0;
1214 while (reglist != 0) {
1215 n++;
1216 reglist &= reglist - 1; // clear one bit
1217 }
1218 return n;
1219}
1220
1221
Steve Block44f0eee2011-05-26 01:26:41 +01001222struct JSCallerSavedCodeData {
1223 JSCallerSavedCodeData() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001224 int i = 0;
1225 for (int r = 0; r < kNumRegs; r++)
1226 if ((kJSCallerSaved & (1 << r)) != 0)
1227 reg_code[i++] = r;
1228
1229 ASSERT(i == kNumJSCallerSaved);
1230 }
Steve Block44f0eee2011-05-26 01:26:41 +01001231 int reg_code[kNumJSCallerSaved];
1232};
1233
1234
Ben Murdoch85b71792012-04-11 18:30:58 +01001235static const JSCallerSavedCodeData kCallerSavedCodeData;
1236
Steve Block44f0eee2011-05-26 01:26:41 +01001237
1238int JSCallerSavedCode(int n) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001239 ASSERT(0 <= n && n < kNumJSCallerSaved);
Ben Murdoch85b71792012-04-11 18:30:58 +01001240 return kCallerSavedCodeData.reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001241}
1242
1243
Steve Block6ded16b2010-05-10 14:33:55 +01001244#define DEFINE_WRAPPER(type, field) \
1245class field##_Wrapper : public ZoneObject { \
1246 public: /* NOLINT */ \
1247 field##_Wrapper(const field& original) : frame_(original) { \
1248 } \
1249 field frame_; \
1250};
1251STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1252#undef DEFINE_WRAPPER
1253
1254static StackFrame* AllocateFrameCopy(StackFrame* frame) {
1255#define FRAME_TYPE_CASE(type, field) \
1256 case StackFrame::type: { \
1257 field##_Wrapper* wrapper = \
1258 new field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
1259 return &wrapper->frame_; \
1260 }
1261
1262 switch (frame->type()) {
1263 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1264 default: UNREACHABLE();
1265 }
1266#undef FRAME_TYPE_CASE
1267 return NULL;
1268}
1269
1270Vector<StackFrame*> CreateStackMap() {
1271 ZoneList<StackFrame*> list(10);
1272 for (StackFrameIterator it; !it.done(); it.Advance()) {
1273 StackFrame* frame = AllocateFrameCopy(it.frame());
1274 list.Add(frame);
1275 }
1276 return list.ToVector();
1277}
1278
1279
Steve Blocka7e24c12009-10-30 11:49:00 +00001280} } // namespace v8::internal