blob: 4402496f1824585c7a87cf66a9642d4a02674068 [file] [log] [blame]
Ben Murdochc7cc0282012-03-05 14:35:55 +00001// Copyright 2012 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_;
158 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 Murdoch592a9fc2012-03-05 11:04:45 +0000369 Address inner_pointer,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100370 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100371 unsigned* stack_slots) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000372 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
373 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100374 if (!entry->safepoint_entry.is_valid()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000375 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100376 ASSERT(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100377 } else {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000378 ASSERT(entry->safepoint_entry.Equals(
379 entry->code->GetSafepointEntry(inner_pointer)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100380 }
381
382 // Fill in the results and return the code.
383 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100384 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100385 *stack_slots = code->stack_slots();
386 return code;
387}
388
389
Steve Blocka7e24c12009-10-30 11:49:00 +0000390bool StackFrame::HasHandler() const {
391 StackHandlerIterator it(this, top_handler());
392 return !it.done();
393}
394
Ben Murdochb0fe1622011-05-05 13:52:32 +0100395
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000396#ifdef DEBUG
397static bool GcSafeCodeContains(HeapObject* object, Address addr);
398#endif
399
400
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100401void StackFrame::IteratePc(ObjectVisitor* v,
402 Address* pc_address,
403 Code* holder) {
404 Address pc = *pc_address;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000405 ASSERT(GcSafeCodeContains(holder, pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100406 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
407 Object* code = holder;
408 v->VisitPointer(&code);
409 if (code != holder) {
410 holder = reinterpret_cast<Code*>(code);
411 pc = holder->instruction_start() + pc_offset;
412 *pc_address = pc;
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000414}
415
416
Ben Murdoch8b112d22011-06-08 16:22:53 +0100417StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100418 ASSERT(state->fp != NULL);
419 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
420 return ARGUMENTS_ADAPTOR;
Steve Blocka7e24c12009-10-30 11:49:00 +0000421 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100422 // The marker and function offsets overlap. If the marker isn't a
423 // smi then the frame is a JavaScript frame -- and the marker is
424 // really the function.
425 const int offset = StandardFrameConstants::kMarkerOffset;
426 Object* marker = Memory::Object_at(state->fp + offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100427 if (!marker->IsSmi()) {
428 // If we're using a "safe" stack iterator, we treat optimized
429 // frames as normal JavaScript frames to avoid having to look
430 // into the heap to determine the state. This is safe as long
431 // as nobody tries to GC...
Ben Murdoch8b112d22011-06-08 16:22:53 +0100432 if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT;
433 Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100434 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
435 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
436 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100437 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000438}
439
440
Steve Blocka7e24c12009-10-30 11:49:00 +0000441
442StackFrame::Type StackFrame::GetCallerState(State* state) const {
443 ComputeCallerState(state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100444 return ComputeType(isolate(), state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000445}
446
447
Iain Merrick75681382010-08-19 15:07:18 +0100448Code* EntryFrame::unchecked_code() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100449 return HEAP->raw_unchecked_js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000450}
451
452
453void EntryFrame::ComputeCallerState(State* state) const {
454 GetCallerState(state);
455}
456
457
Steve Block6ded16b2010-05-10 14:33:55 +0100458void EntryFrame::SetCallerFp(Address caller_fp) {
459 const int offset = EntryFrameConstants::kCallerFPOffset;
460 Memory::Address_at(this->fp() + offset) = caller_fp;
461}
462
463
Steve Blocka7e24c12009-10-30 11:49:00 +0000464StackFrame::Type EntryFrame::GetCallerState(State* state) const {
465 const int offset = EntryFrameConstants::kCallerFPOffset;
466 Address fp = Memory::Address_at(this->fp() + offset);
467 return ExitFrame::GetStateForFramePointer(fp, state);
468}
469
470
Iain Merrick75681382010-08-19 15:07:18 +0100471Code* EntryConstructFrame::unchecked_code() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100472 return HEAP->raw_unchecked_js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000473}
474
475
Steve Blockd0582a62009-12-15 09:54:21 +0000476Object*& ExitFrame::code_slot() const {
477 const int offset = ExitFrameConstants::kCodeOffset;
478 return Memory::Object_at(fp() + offset);
479}
480
481
Iain Merrick75681382010-08-19 15:07:18 +0100482Code* ExitFrame::unchecked_code() const {
483 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000484}
485
486
487void ExitFrame::ComputeCallerState(State* state) const {
Ben Murdochc7cc0282012-03-05 14:35:55 +0000488 // Set up the caller state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000489 state->sp = caller_sp();
490 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
491 state->pc_address
492 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
493}
494
495
Steve Block6ded16b2010-05-10 14:33:55 +0100496void ExitFrame::SetCallerFp(Address caller_fp) {
497 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
498}
499
500
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100501void ExitFrame::Iterate(ObjectVisitor* v) const {
502 // The arguments are traversed as part of the expression stack of
503 // the calling frame.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100504 IteratePc(v, pc_address(), LookupCode());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100505 v->VisitPointer(&code_slot());
506}
507
508
Steve Blocka7e24c12009-10-30 11:49:00 +0000509Address ExitFrame::GetCallerStackPointer() const {
510 return fp() + ExitFrameConstants::kCallerSPDisplacement;
511}
512
513
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100514StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
515 if (fp == 0) return NONE;
516 Address sp = ComputeStackPointer(fp);
517 FillState(fp, sp, state);
518 ASSERT(*state->pc_address != NULL);
519 return EXIT;
520}
521
522
523void ExitFrame::FillState(Address fp, Address sp, State* state) {
524 state->sp = sp;
525 state->fp = fp;
526 state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
527}
528
529
Steve Blocka7e24c12009-10-30 11:49:00 +0000530Address StandardFrame::GetExpressionAddress(int n) const {
531 const int offset = StandardFrameConstants::kExpressionsOffset;
532 return fp() + offset - n * kPointerSize;
533}
534
535
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000536Object* StandardFrame::GetExpression(Address fp, int index) {
537 return Memory::Object_at(GetExpressionAddress(fp, index));
538}
539
540
541Address StandardFrame::GetExpressionAddress(Address fp, int n) {
542 const int offset = StandardFrameConstants::kExpressionsOffset;
543 return fp + offset - n * kPointerSize;
544}
545
546
Steve Blocka7e24c12009-10-30 11:49:00 +0000547int StandardFrame::ComputeExpressionsCount() const {
548 const int offset =
549 StandardFrameConstants::kExpressionsOffset + kPointerSize;
550 Address base = fp() + offset;
551 Address limit = sp();
552 ASSERT(base >= limit); // stack grows downwards
553 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000554 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000555}
556
557
558void StandardFrame::ComputeCallerState(State* state) const {
559 state->sp = caller_sp();
560 state->fp = caller_fp();
561 state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
562}
563
564
Steve Block6ded16b2010-05-10 14:33:55 +0100565void StandardFrame::SetCallerFp(Address caller_fp) {
566 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
567 caller_fp;
568}
569
570
Steve Blocka7e24c12009-10-30 11:49:00 +0000571bool StandardFrame::IsExpressionInsideHandler(int n) const {
572 Address address = GetExpressionAddress(n);
573 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
574 if (it.handler()->includes(address)) return true;
575 }
576 return false;
577}
578
579
Ben Murdochb0fe1622011-05-05 13:52:32 +0100580void OptimizedFrame::Iterate(ObjectVisitor* v) const {
581#ifdef DEBUG
582 // Make sure that optimized frames do not contain any stack handlers.
583 StackHandlerIterator it(this, top_handler());
584 ASSERT(it.done());
585#endif
586
587 // Make sure that we're not doing "safe" stack frame iteration. We cannot
588 // possibly find pointers in optimized frames in that state.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100589 ASSERT(!SafeStackFrameIterator::is_active(isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100590
591 // Compute the safepoint information.
592 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100593 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100594 Code* code = StackFrame::GetSafepointData(
Ben Murdoch8b112d22011-06-08 16:22:53 +0100595 isolate(), pc(), &safepoint_entry, &stack_slots);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100596 unsigned slot_space = stack_slots * kPointerSize;
597
Ben Murdoch8b112d22011-06-08 16:22:53 +0100598 // Visit the outgoing parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100599 Object** parameters_base = &Memory::Object_at(sp());
600 Object** parameters_limit = &Memory::Object_at(
601 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
602
Ben Murdochb8e0da22011-05-16 14:20:40 +0100603 // Visit the parameters that may be on top of the saved registers.
604 if (safepoint_entry.argument_count() > 0) {
605 v->VisitPointers(parameters_base,
606 parameters_base + safepoint_entry.argument_count());
607 parameters_base += safepoint_entry.argument_count();
608 }
609
610 // Skip saved double registers.
611 if (safepoint_entry.has_doubles()) {
612 parameters_base += DoubleRegister::kNumAllocatableRegisters *
613 kDoubleSize / kPointerSize;
614 }
615
Ben Murdochb0fe1622011-05-05 13:52:32 +0100616 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100617 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100618 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100619 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100620 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
621 v->VisitPointer(parameters_base + reg_stack_index);
622 }
623 }
624 // Skip the words containing the register values.
625 parameters_base += kNumSafepointRegisters;
626 }
627
628 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100629 uint8_t* safepoint_bits = safepoint_entry.bits();
630 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100631
632 // Visit the rest of the parameters.
633 v->VisitPointers(parameters_base, parameters_limit);
634
635 // Visit pointer spill slots and locals.
636 for (unsigned index = 0; index < stack_slots; index++) {
637 int byte_index = index >> kBitsPerByteLog2;
638 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100639 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100640 v->VisitPointer(parameters_limit + index);
641 }
642 }
643
644 // Visit the context and the function.
645 Object** fixed_base = &Memory::Object_at(
646 fp() + JavaScriptFrameConstants::kFunctionOffset);
647 Object** fixed_limit = &Memory::Object_at(fp());
648 v->VisitPointers(fixed_base, fixed_limit);
649
650 // Visit the return address in the callee and incoming arguments.
651 IteratePc(v, pc_address(), code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000652}
653
654
655bool JavaScriptFrame::IsConstructor() const {
656 Address fp = caller_fp();
657 if (has_adapted_arguments()) {
658 // Skip the arguments adaptor frame and look at the real caller.
659 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
660 }
661 return IsConstructFrame(fp);
662}
663
664
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000665int JavaScriptFrame::GetArgumentsLength() const {
666 // If there is an arguments adaptor frame get the arguments length from it.
667 if (has_adapted_arguments()) {
668 return Smi::cast(GetExpression(caller_fp(), 0))->value();
669 } else {
670 return GetNumberOfIncomingArguments();
671 }
672}
673
674
Iain Merrick75681382010-08-19 15:07:18 +0100675Code* JavaScriptFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000676 JSFunction* function = JSFunction::cast(this->function());
Iain Merrick75681382010-08-19 15:07:18 +0100677 return function->unchecked_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000678}
679
680
Ben Murdoch8b112d22011-06-08 16:22:53 +0100681int JavaScriptFrame::GetNumberOfIncomingArguments() const {
682 ASSERT(!SafeStackFrameIterator::is_active(isolate()) &&
683 isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
684
685 JSFunction* function = JSFunction::cast(this->function());
686 return function->shared()->formal_parameter_count();
687}
688
689
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100690Address JavaScriptFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100691 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100692}
693
694
Ben Murdochb0fe1622011-05-05 13:52:32 +0100695void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
696 ASSERT(functions->length() == 0);
697 functions->Add(JSFunction::cast(function()));
698}
699
700
701void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
702 ASSERT(functions->length() == 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100703 Code* code_pointer = LookupCode();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100704 int offset = static_cast<int>(pc() - code_pointer->address());
705 FrameSummary summary(receiver(),
706 JSFunction::cast(function()),
707 code_pointer,
708 offset,
709 IsConstructor());
710 functions->Add(summary);
711}
712
713
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000714void JavaScriptFrame::PrintTop(FILE* file,
715 bool print_args,
716 bool print_line_number) {
717 // constructor calls
718 HandleScope scope;
719 AssertNoAllocation no_allocation;
720 JavaScriptFrameIterator it;
721 while (!it.done()) {
722 if (it.frame()->is_java_script()) {
723 JavaScriptFrame* frame = it.frame();
724 if (frame->IsConstructor()) PrintF(file, "new ");
725 // function name
Ben Murdochc7cc0282012-03-05 14:35:55 +0000726 Object* maybe_fun = frame->function();
727 if (maybe_fun->IsJSFunction()) {
728 JSFunction* fun = JSFunction::cast(maybe_fun);
729 fun->PrintName();
730 Code* js_code = frame->unchecked_code();
731 Address pc = frame->pc();
732 int code_offset =
733 static_cast<int>(pc - js_code->instruction_start());
734 PrintF("+%d", code_offset);
735 SharedFunctionInfo* shared = fun->shared();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000736 if (print_line_number) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000737 Code* code = Code::cast(
738 v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
739 int source_pos = code->SourcePosition(pc);
740 Object* maybe_script = shared->script();
741 if (maybe_script->IsScript()) {
742 Handle<Script> script(Script::cast(maybe_script));
743 int line = GetScriptLineNumberSafe(script, source_pos) + 1;
744 Object* script_name_raw = script->name();
745 if (script_name_raw->IsString()) {
746 String* script_name = String::cast(script->name());
747 SmartArrayPointer<char> c_script_name =
748 script_name->ToCString(DISALLOW_NULLS,
749 ROBUST_STRING_TRAVERSAL);
750 PrintF(file, " at %s:%d", *c_script_name, line);
751 } else {
752 PrintF(file, "at <unknown>:%d", line);
753 }
754 } else {
755 PrintF(file, " at <unknown>:<unknown>");
756 }
757 }
758 } else {
Ben Murdochc7cc0282012-03-05 14:35:55 +0000759 PrintF("<unknown>");
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000760 }
761
762 if (print_args) {
763 // function arguments
764 // (we are intentionally only printing the actually
765 // supplied parameters, not all parameters required)
766 PrintF(file, "(this=");
767 frame->receiver()->ShortPrint(file);
768 const int length = frame->ComputeParametersCount();
769 for (int i = 0; i < length; i++) {
770 PrintF(file, ", ");
771 frame->GetParameter(i)->ShortPrint(file);
772 }
773 PrintF(file, ")");
774 }
775 break;
776 }
777 it.Advance();
778 }
779}
780
781
Ben Murdochb0fe1622011-05-05 13:52:32 +0100782void FrameSummary::Print() {
783 PrintF("receiver: ");
784 receiver_->ShortPrint();
785 PrintF("\nfunction: ");
786 function_->shared()->DebugName()->ShortPrint();
787 PrintF("\ncode: ");
788 code_->ShortPrint();
789 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
790 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
791 PrintF("\npc: %d\n", offset_);
792}
793
794
795void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
796 ASSERT(frames->length() == 0);
797 ASSERT(is_optimized());
798
Steve Block1e0659c2011-05-24 12:43:12 +0100799 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100800 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
801
802 // BUG(3243555): Since we don't have a lazy-deopt registered at
803 // throw-statements, we can't use the translation at the call-site of
804 // throw. An entry with no deoptimization index indicates a call-site
805 // without a lazy-deopt. As a consequence we are not allowed to inline
806 // functions containing throw.
807 if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
808 JavaScriptFrame::Summarize(frames);
809 return;
810 }
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);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000816 it.Next(); // Drop frame count.
817 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100818
819 // We create the summary in reverse order because the frames
820 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdochc7cc0282012-03-05 14:35:55 +0000821 int i = jsframe_count;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100822 while (i > 0) {
823 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochc7cc0282012-03-05 14:35:55 +0000824 if (opcode == Translation::JS_FRAME) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100825 // We don't inline constructor calls, so only the first, outermost
826 // frame can be a constructor frame in case of inlining.
Ben Murdochc7cc0282012-03-05 14:35:55 +0000827 bool is_constructor = (i == jsframe_count) && IsConstructor();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100828
829 i--;
830 int ast_id = it.Next();
831 int function_id = it.Next();
832 it.Next(); // Skip height.
833 JSFunction* function =
834 JSFunction::cast(data->LiteralArray()->get(function_id));
835
836 // The translation commands are ordered and the receiver is always
837 // at the first position. Since we are always at a call when we need
838 // to construct a stack trace, the receiver is always in a stack slot.
839 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch257744e2011-11-30 15:57:28 +0000840 ASSERT(opcode == Translation::STACK_SLOT ||
841 opcode == Translation::LITERAL);
842 int index = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100843
844 // Get the correct receiver in the optimized frame.
845 Object* receiver = NULL;
Ben Murdoch257744e2011-11-30 15:57:28 +0000846 if (opcode == Translation::LITERAL) {
847 receiver = data->LiteralArray()->get(index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100848 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +0000849 // Positive index means the value is spilled to the locals
850 // area. Negative means it is stored in the incoming parameter
851 // area.
852 if (index >= 0) {
853 receiver = GetExpression(index);
854 } else {
855 // Index -1 overlaps with last parameter, -n with the first parameter,
856 // (-n - 1) with the receiver with n being the number of parameters
857 // of the outermost, optimized frame.
858 int parameter_count = ComputeParametersCount();
859 int parameter_index = index + parameter_count;
860 receiver = (parameter_index == -1)
861 ? this->receiver()
862 : this->GetParameter(parameter_index);
863 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100864 }
865
866 Code* code = function->shared()->code();
867 DeoptimizationOutputData* output_data =
868 DeoptimizationOutputData::cast(code->deoptimization_data());
869 unsigned entry = Deoptimizer::GetOutputInfo(output_data,
870 ast_id,
871 function->shared());
872 unsigned pc_offset =
873 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
874 ASSERT(pc_offset > 0);
875
876 FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
877 frames->Add(summary);
878 } else {
879 // Skip over operands to advance to the next opcode.
880 it.Skip(Translation::NumberOfOperandsFor(opcode));
881 }
882 }
883}
884
885
886DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
887 int* deopt_index) {
888 ASSERT(is_optimized());
889
890 JSFunction* opt_function = JSFunction::cast(function());
891 Code* code = opt_function->code();
892
893 // The code object may have been replaced by lazy deoptimization. Fall
894 // back to a slow search in this case to find the original optimized
895 // code object.
896 if (!code->contains(pc())) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000897 code = isolate()->inner_pointer_to_code_cache()->
898 GcSafeFindCodeForInnerPointer(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100899 }
900 ASSERT(code != NULL);
901 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
902
Ben Murdochb8e0da22011-05-16 14:20:40 +0100903 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
904 *deopt_index = safepoint_entry.deoptimization_index();
Steve Block1e0659c2011-05-24 12:43:12 +0100905 ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100906
907 return DeoptimizationInputData::cast(code->deoptimization_data());
908}
909
910
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000911int OptimizedFrame::GetInlineCount() {
912 ASSERT(is_optimized());
913
914 int deopt_index = Safepoint::kNoDeoptimizationIndex;
915 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
916
917 TranslationIterator it(data->TranslationByteArray(),
918 data->TranslationIndex(deopt_index)->value());
919 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
920 ASSERT(opcode == Translation::BEGIN);
921 USE(opcode);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000922 it.Next(); // Drop frame count.
923 int jsframe_count = it.Next();
924 return jsframe_count;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000925}
926
927
Ben Murdochb0fe1622011-05-05 13:52:32 +0100928void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
929 ASSERT(functions->length() == 0);
930 ASSERT(is_optimized());
931
Steve Block1e0659c2011-05-24 12:43:12 +0100932 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100933 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
934
935 TranslationIterator it(data->TranslationByteArray(),
936 data->TranslationIndex(deopt_index)->value());
937 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
938 ASSERT(opcode == Translation::BEGIN);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000939 it.Next(); // Drop frame count.
940 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100941
942 // We insert the frames in reverse order because the frames
943 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdochc7cc0282012-03-05 14:35:55 +0000944 while (jsframe_count > 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100945 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochc7cc0282012-03-05 14:35:55 +0000946 if (opcode == Translation::JS_FRAME) {
947 jsframe_count--;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100948 it.Next(); // Skip ast id.
949 int function_id = it.Next();
950 it.Next(); // Skip height.
951 JSFunction* function =
952 JSFunction::cast(data->LiteralArray()->get(function_id));
953 functions->Add(function);
954 } else {
955 // Skip over operands to advance to the next opcode.
956 it.Skip(Translation::NumberOfOperandsFor(opcode));
957 }
958 }
959}
960
961
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000962int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
963 return Smi::cast(GetExpression(0))->value();
964}
965
966
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100967Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100968 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100969}
970
971
972Address InternalFrame::GetCallerStackPointer() const {
973 // Internal frames have no arguments. The stack pointer of the
974 // caller is at a fixed offset from the frame pointer.
975 return fp() + StandardFrameConstants::kCallerSPOffset;
976}
977
978
Iain Merrick75681382010-08-19 15:07:18 +0100979Code* ArgumentsAdaptorFrame::unchecked_code() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100980 return isolate()->builtins()->builtin(
Steve Block44f0eee2011-05-26 01:26:41 +0100981 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +0000982}
983
984
Iain Merrick75681382010-08-19 15:07:18 +0100985Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000986 const int offset = InternalFrameConstants::kCodeOffset;
987 Object* code = Memory::Object_at(fp() + offset);
988 ASSERT(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +0100989 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000990}
991
992
993void StackFrame::PrintIndex(StringStream* accumulator,
994 PrintMode mode,
995 int index) {
996 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
997}
998
999
1000void JavaScriptFrame::Print(StringStream* accumulator,
1001 PrintMode mode,
1002 int index) const {
1003 HandleScope scope;
1004 Object* receiver = this->receiver();
1005 Object* function = this->function();
1006
1007 accumulator->PrintSecurityTokenIfChanged(function);
1008 PrintIndex(accumulator, mode, index);
1009 Code* code = NULL;
1010 if (IsConstructor()) accumulator->Add("new ");
1011 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +01001012
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001013 // Get scope information for nicer output, if possible. If code is NULL, or
1014 // doesn't contain scope info, scope_info will return 0 for the number of
1015 // parameters, stack local variables, context local variables, stack slots,
1016 // or context slots.
1017 Handle<ScopeInfo> scope_info(ScopeInfo::Empty());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001018
Steve Block6ded16b2010-05-10 14:33:55 +01001019 if (function->IsJSFunction()) {
1020 Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001021 scope_info = Handle<ScopeInfo>(shared->scope_info());
Steve Block6ded16b2010-05-10 14:33:55 +01001022 Object* script_obj = shared->script();
1023 if (script_obj->IsScript()) {
1024 Handle<Script> script(Script::cast(script_obj));
1025 accumulator->Add(" [");
1026 accumulator->PrintName(script->name());
1027
1028 Address pc = this->pc();
1029 if (code != NULL && code->kind() == Code::FUNCTION &&
Leon Clarkeac952652010-07-15 11:15:24 +01001030 pc >= code->instruction_start() && pc < code->instruction_end()) {
Steve Block6ded16b2010-05-10 14:33:55 +01001031 int source_pos = code->SourcePosition(pc);
1032 int line = GetScriptLineNumberSafe(script, source_pos) + 1;
1033 accumulator->Add(":%d", line);
1034 } else {
1035 int function_start_pos = shared->start_position();
1036 int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
1037 accumulator->Add(":~%d", line);
1038 }
1039
1040 accumulator->Add("] ");
1041 }
1042 }
1043
Steve Blocka7e24c12009-10-30 11:49:00 +00001044 accumulator->Add("(this=%o", receiver);
1045
Steve Blocka7e24c12009-10-30 11:49:00 +00001046 // Print the parameters.
1047 int parameters_count = ComputeParametersCount();
1048 for (int i = 0; i < parameters_count; i++) {
1049 accumulator->Add(",");
1050 // If we have a name for the parameter we print it. Nameless
1051 // parameters are either because we have more actual parameters
1052 // than formal parameters or because we have no scope information.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001053 if (i < scope_info->ParameterCount()) {
1054 accumulator->PrintName(scope_info->ParameterName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001055 accumulator->Add("=");
1056 }
1057 accumulator->Add("%o", GetParameter(i));
1058 }
1059
1060 accumulator->Add(")");
1061 if (mode == OVERVIEW) {
1062 accumulator->Add("\n");
1063 return;
1064 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001065 if (is_optimized()) {
1066 accumulator->Add(" {\n// optimized frame\n}\n");
1067 return;
1068 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001069 accumulator->Add(" {\n");
1070
1071 // Compute the number of locals and expression stack elements.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001072 int stack_locals_count = scope_info->StackLocalCount();
1073 int heap_locals_count = scope_info->ContextLocalCount();
Steve Blocka7e24c12009-10-30 11:49:00 +00001074 int expressions_count = ComputeExpressionsCount();
1075
1076 // Print stack-allocated local variables.
1077 if (stack_locals_count > 0) {
1078 accumulator->Add(" // stack-allocated locals\n");
1079 }
1080 for (int i = 0; i < stack_locals_count; i++) {
1081 accumulator->Add(" var ");
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001082 accumulator->PrintName(scope_info->StackLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001083 accumulator->Add(" = ");
1084 if (i < expressions_count) {
1085 accumulator->Add("%o", GetExpression(i));
1086 } else {
1087 accumulator->Add("// no expression found - inconsistent frame?");
1088 }
1089 accumulator->Add("\n");
1090 }
1091
1092 // Try to get hold of the context of this frame.
1093 Context* context = NULL;
1094 if (this->context() != NULL && this->context()->IsContext()) {
1095 context = Context::cast(this->context());
1096 }
1097
1098 // Print heap-allocated local variables.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001099 if (heap_locals_count > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001100 accumulator->Add(" // heap-allocated locals\n");
1101 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001102 for (int i = 0; i < heap_locals_count; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001103 accumulator->Add(" var ");
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001104 accumulator->PrintName(scope_info->ContextLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001105 accumulator->Add(" = ");
1106 if (context != NULL) {
1107 if (i < context->length()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001108 accumulator->Add("%o", context->get(Context::MIN_CONTEXT_SLOTS + i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001109 } else {
1110 accumulator->Add(
1111 "// warning: missing context slot - inconsistent frame?");
1112 }
1113 } else {
1114 accumulator->Add("// warning: no context found - inconsistent frame?");
1115 }
1116 accumulator->Add("\n");
1117 }
1118
1119 // Print the expression stack.
1120 int expressions_start = stack_locals_count;
1121 if (expressions_start < expressions_count) {
1122 accumulator->Add(" // expression stack (top to bottom)\n");
1123 }
1124 for (int i = expressions_count - 1; i >= expressions_start; i--) {
1125 if (IsExpressionInsideHandler(i)) continue;
1126 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1127 }
1128
1129 // Print details about the function.
1130 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1131 SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
1132 accumulator->Add("--------- s o u r c e c o d e ---------\n");
1133 shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
1134 accumulator->Add("\n-----------------------------------------\n");
1135 }
1136
1137 accumulator->Add("}\n\n");
1138}
1139
1140
1141void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1142 PrintMode mode,
1143 int index) const {
1144 int actual = ComputeParametersCount();
1145 int expected = -1;
1146 Object* function = this->function();
1147 if (function->IsJSFunction()) {
1148 expected = JSFunction::cast(function)->shared()->formal_parameter_count();
1149 }
1150
1151 PrintIndex(accumulator, mode, index);
1152 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1153 if (mode == OVERVIEW) {
1154 accumulator->Add("\n");
1155 return;
1156 }
1157 accumulator->Add(" {\n");
1158
1159 // Print actual arguments.
1160 if (actual > 0) accumulator->Add(" // actual arguments\n");
1161 for (int i = 0; i < actual; i++) {
1162 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1163 if (expected != -1 && i >= expected) {
1164 accumulator->Add(" // not passed to callee");
1165 }
1166 accumulator->Add("\n");
1167 }
1168
1169 accumulator->Add("}\n\n");
1170}
1171
1172
1173void EntryFrame::Iterate(ObjectVisitor* v) const {
1174 StackHandlerIterator it(this, top_handler());
1175 ASSERT(!it.done());
1176 StackHandler* handler = it.handler();
1177 ASSERT(handler->is_entry());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001178 handler->Iterate(v, LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001179#ifdef DEBUG
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001180 // Make sure that the entry frame does not contain more than one
1181 // stack handler.
Steve Blocka7e24c12009-10-30 11:49:00 +00001182 it.Advance();
1183 ASSERT(it.done());
1184#endif
Ben Murdoch8b112d22011-06-08 16:22:53 +01001185 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001186}
1187
1188
1189void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
1190 const int offset = StandardFrameConstants::kContextOffset;
1191 Object** base = &Memory::Object_at(sp());
1192 Object** limit = &Memory::Object_at(fp() + offset) + 1;
1193 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1194 StackHandler* handler = it.handler();
1195 // Traverse pointers down to - but not including - the next
1196 // handler in the handler chain. Update the base to skip the
1197 // handler and allow the handler to traverse its own pointers.
1198 const Address address = handler->address();
1199 v->VisitPointers(base, reinterpret_cast<Object**>(address));
1200 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1201 // Traverse the pointers in the handler itself.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001202 handler->Iterate(v, LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001203 }
1204 v->VisitPointers(base, limit);
1205}
1206
1207
1208void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1209 IterateExpressions(v);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001210 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001211}
1212
1213
1214void InternalFrame::Iterate(ObjectVisitor* v) const {
1215 // Internal frames only have object pointers on the expression stack
1216 // as they never have any arguments.
1217 IterateExpressions(v);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001218 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001219}
1220
1221
1222// -------------------------------------------------------------------------
1223
1224
1225JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
1226 ASSERT(n >= 0);
1227 for (int i = 0; i <= n; i++) {
1228 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1229 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1230 iterator_.Advance();
1231 }
1232 UNREACHABLE();
1233 return NULL;
1234}
1235
1236
1237// -------------------------------------------------------------------------
1238
1239
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001240static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1241 MapWord map_word = object->map_word();
1242 return map_word.IsForwardingAddress() ?
1243 map_word.ToForwardingAddress()->map() : map_word.ToMap();
1244}
1245
1246
1247static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1248 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1249}
1250
1251
1252#ifdef DEBUG
1253static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1254 Map* map = GcSafeMapOfCodeSpaceObject(code);
1255 ASSERT(map == code->GetHeap()->code_map());
1256 Address start = code->address();
1257 Address end = code->address() + code->SizeFromMap(map);
1258 return start <= addr && addr < end;
1259}
1260#endif
1261
1262
1263Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1264 Address inner_pointer) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001265 Code* code = reinterpret_cast<Code*>(object);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001266 ASSERT(code != NULL && GcSafeCodeContains(code, inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001267 return code;
1268}
1269
1270
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001271Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1272 Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001273 Heap* heap = isolate_->heap();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001274 // Check if the inner pointer points into a large object chunk.
1275 LargePage* large_page = heap->lo_space()->FindPageContainingPc(inner_pointer);
1276 if (large_page != NULL) {
1277 return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1278 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001279
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001280 // Iterate through the page until we reach the end or find an object starting
1281 // after the inner pointer.
1282 Page* page = Page::FromAddress(inner_pointer);
1283
1284 Address addr = page->skip_list()->StartFor(inner_pointer);
1285
1286 Address top = heap->code_space()->top();
1287 Address limit = heap->code_space()->limit();
1288
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001289 while (true) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001290 if (addr == top && addr != limit) {
1291 addr = limit;
1292 continue;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001293 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001294
1295 HeapObject* obj = HeapObject::FromAddress(addr);
1296 int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1297 Address next_addr = addr + obj_size;
1298 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1299 addr = next_addr;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001300 }
1301}
1302
Ben Murdochb0fe1622011-05-05 13:52:32 +01001303
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001304InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1305 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001306 isolate_->counters()->pc_to_code()->Increment();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001307 ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001308 uint32_t hash = ComputeIntegerHash(
Ben Murdochc7cc0282012-03-05 14:35:55 +00001309 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)),
1310 v8::internal::kZeroHashSeed);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001311 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1312 InnerPointerToCodeCacheEntry* entry = cache(index);
1313 if (entry->inner_pointer == inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001314 isolate_->counters()->pc_to_code_cached()->Increment();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001315 ASSERT(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001316 } else {
1317 // Because this code may be interrupted by a profiling signal that
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001318 // also queries the cache, we cannot update inner_pointer before the code
1319 // has been set. Otherwise, we risk trying to use a cache entry before
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001320 // the code has been computed.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001321 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001322 entry->safepoint_entry.Reset();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001323 entry->inner_pointer = inner_pointer;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001324 }
1325 return entry;
1326}
1327
1328
1329// -------------------------------------------------------------------------
1330
Steve Blocka7e24c12009-10-30 11:49:00 +00001331int NumRegs(RegList reglist) {
1332 int n = 0;
1333 while (reglist != 0) {
1334 n++;
1335 reglist &= reglist - 1; // clear one bit
1336 }
1337 return n;
1338}
1339
1340
Steve Block44f0eee2011-05-26 01:26:41 +01001341struct JSCallerSavedCodeData {
1342 JSCallerSavedCodeData() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001343 int i = 0;
1344 for (int r = 0; r < kNumRegs; r++)
1345 if ((kJSCallerSaved & (1 << r)) != 0)
1346 reg_code[i++] = r;
1347
1348 ASSERT(i == kNumJSCallerSaved);
1349 }
Steve Block44f0eee2011-05-26 01:26:41 +01001350 int reg_code[kNumJSCallerSaved];
1351};
1352
1353
1354static const JSCallerSavedCodeData kCallerSavedCodeData;
1355
1356
1357int JSCallerSavedCode(int n) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001358 ASSERT(0 <= n && n < kNumJSCallerSaved);
Steve Block44f0eee2011-05-26 01:26:41 +01001359 return kCallerSavedCodeData.reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001360}
1361
1362
Steve Block6ded16b2010-05-10 14:33:55 +01001363#define DEFINE_WRAPPER(type, field) \
1364class field##_Wrapper : public ZoneObject { \
1365 public: /* NOLINT */ \
1366 field##_Wrapper(const field& original) : frame_(original) { \
1367 } \
1368 field frame_; \
1369};
1370STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1371#undef DEFINE_WRAPPER
1372
1373static StackFrame* AllocateFrameCopy(StackFrame* frame) {
1374#define FRAME_TYPE_CASE(type, field) \
1375 case StackFrame::type: { \
1376 field##_Wrapper* wrapper = \
1377 new field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
1378 return &wrapper->frame_; \
1379 }
1380
1381 switch (frame->type()) {
1382 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1383 default: UNREACHABLE();
1384 }
1385#undef FRAME_TYPE_CASE
1386 return NULL;
1387}
1388
1389Vector<StackFrame*> CreateStackMap() {
1390 ZoneList<StackFrame*> list(10);
1391 for (StackFrameIterator it; !it.done(); it.Advance()) {
1392 StackFrame* frame = AllocateFrameCopy(it.frame());
1393 list.Add(frame);
1394 }
1395 return list.ToVector();
1396}
1397
1398
Steve Blocka7e24c12009-10-30 11:49:00 +00001399} } // namespace v8::internal