blob: 0571a813f5e56b45922ac6ee3a76dc78940749ad [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// 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"
Ben Murdoch3ef787d2012-04-12 10:51:47 +010034#include "lazy-instance.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035#include "mark-compact.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010036#include "safepoint-table.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000037#include "scopeinfo.h"
38#include "string-stream.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000040#include "allocation-inl.h"
41
Steve Blocka7e24c12009-10-30 11:49:00 +000042namespace v8 {
43namespace internal {
44
Ben Murdoch3ef787d2012-04-12 10:51:47 +010045
46static ReturnAddressLocationResolver return_address_location_resolver = NULL;
47
48
49// Resolves pc_address through the resolution address function if one is set.
50static inline Address* ResolveReturnAddressLocation(Address* pc_address) {
51 if (return_address_location_resolver == NULL) {
52 return pc_address;
53 } else {
54 return reinterpret_cast<Address*>(
55 return_address_location_resolver(
56 reinterpret_cast<uintptr_t>(pc_address)));
57 }
58}
59
60
Steve Blocka7e24c12009-10-30 11:49:00 +000061// Iterator that supports traversing the stack handlers of a
62// particular frame. Needs to know the top of the handler chain.
63class StackHandlerIterator BASE_EMBEDDED {
64 public:
65 StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
66 : limit_(frame->fp()), handler_(handler) {
67 // Make sure the handler has already been unwound to this frame.
68 ASSERT(frame->sp() <= handler->address());
69 }
70
71 StackHandler* handler() const { return handler_; }
72
73 bool done() {
74 return handler_ == NULL || handler_->address() > limit_;
75 }
76 void Advance() {
77 ASSERT(!done());
78 handler_ = handler_->next();
79 }
80
81 private:
82 const Address limit_;
83 StackHandler* handler_;
84};
85
86
87// -------------------------------------------------------------------------
88
89
90#define INITIALIZE_SINGLETON(type, field) field##_(this),
91StackFrameIterator::StackFrameIterator()
Ben Murdoch8b112d22011-06-08 16:22:53 +010092 : isolate_(Isolate::Current()),
93 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
Steve Block44f0eee2011-05-26 01:26:41 +010094 frame_(NULL), handler_(NULL),
Ben Murdoch8b112d22011-06-08 16:22:53 +010095 thread_(isolate_->thread_local_top()),
Steve Blocka7e24c12009-10-30 11:49:00 +000096 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
97 Reset();
98}
Ben Murdoch8b112d22011-06-08 16:22:53 +010099StackFrameIterator::StackFrameIterator(Isolate* isolate)
100 : isolate_(isolate),
101 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
102 frame_(NULL), handler_(NULL),
103 thread_(isolate_->thread_local_top()),
104 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
105 Reset();
106}
107StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
108 : isolate_(isolate),
109 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
Steve Blocka7e24c12009-10-30 11:49:00 +0000110 frame_(NULL), handler_(NULL), thread_(t),
111 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
112 Reset();
113}
Steve Block44f0eee2011-05-26 01:26:41 +0100114StackFrameIterator::StackFrameIterator(Isolate* isolate,
115 bool use_top, Address fp, Address sp)
Ben Murdoch8b112d22011-06-08 16:22:53 +0100116 : isolate_(isolate),
117 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
Steve Blocka7e24c12009-10-30 11:49:00 +0000118 frame_(NULL), handler_(NULL),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100119 thread_(use_top ? isolate_->thread_local_top() : NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000120 fp_(use_top ? NULL : fp), sp_(sp),
121 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
122 &StackFrameIterator::AdvanceWithoutHandler) {
123 if (use_top || fp != NULL) {
124 Reset();
125 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000126}
127
128#undef INITIALIZE_SINGLETON
129
130
131void StackFrameIterator::AdvanceWithHandler() {
132 ASSERT(!done());
133 // Compute the state of the calling frame before restoring
134 // callee-saved registers and unwinding handlers. This allows the
135 // frame code that computes the caller state to access the top
136 // handler and the value of any callee-saved register if needed.
137 StackFrame::State state;
138 StackFrame::Type type = frame_->GetCallerState(&state);
139
140 // Unwind handlers corresponding to the current frame.
141 StackHandlerIterator it(frame_, handler_);
142 while (!it.done()) it.Advance();
143 handler_ = it.handler();
144
145 // Advance to the calling frame.
146 frame_ = SingletonFor(type, &state);
147
148 // When we're done iterating over the stack frames, the handler
149 // chain must have been completely unwound.
150 ASSERT(!done() || handler_ == NULL);
151}
152
153
154void StackFrameIterator::AdvanceWithoutHandler() {
155 // A simpler version of Advance which doesn't care about handler.
156 ASSERT(!done());
157 StackFrame::State state;
158 StackFrame::Type type = frame_->GetCallerState(&state);
159 frame_ = SingletonFor(type, &state);
160}
161
162
163void StackFrameIterator::Reset() {
164 StackFrame::State state;
165 StackFrame::Type type;
166 if (thread_ != NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100167 type = ExitFrame::GetStateForFramePointer(
168 Isolate::c_entry_fp(thread_), &state);
169 handler_ = StackHandler::FromAddress(
170 Isolate::handler(thread_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 } else {
172 ASSERT(fp_ != NULL);
173 state.fp = fp_;
174 state.sp = sp_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100175 state.pc_address = ResolveReturnAddressLocation(
176 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100177 type = StackFrame::ComputeType(isolate(), &state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000178 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100179 if (SingletonFor(type) == NULL) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 frame_ = SingletonFor(type, &state);
181}
182
183
184StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
185 StackFrame::State* state) {
186 if (type == StackFrame::NONE) return NULL;
187 StackFrame* result = SingletonFor(type);
188 ASSERT(result != NULL);
189 result->state_ = *state;
190 return result;
191}
192
193
194StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
195#define FRAME_TYPE_CASE(type, field) \
196 case StackFrame::type: result = &field##_; break;
197
198 StackFrame* result = NULL;
199 switch (type) {
200 case StackFrame::NONE: return NULL;
201 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
202 default: break;
203 }
204 return result;
205
206#undef FRAME_TYPE_CASE
207}
208
209
210// -------------------------------------------------------------------------
211
212
213StackTraceFrameIterator::StackTraceFrameIterator() {
Leon Clarke4515c472010-02-03 11:58:03 +0000214 if (!done() && !IsValidFrame()) Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +0000215}
216
217
Ben Murdoch8b112d22011-06-08 16:22:53 +0100218StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
219 : JavaScriptFrameIterator(isolate) {
220 if (!done() && !IsValidFrame()) Advance();
221}
222
223
Steve Blocka7e24c12009-10-30 11:49:00 +0000224void StackTraceFrameIterator::Advance() {
225 while (true) {
226 JavaScriptFrameIterator::Advance();
227 if (done()) return;
Leon Clarke4515c472010-02-03 11:58:03 +0000228 if (IsValidFrame()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000229 }
230}
231
Leon Clarke4515c472010-02-03 11:58:03 +0000232bool StackTraceFrameIterator::IsValidFrame() {
233 if (!frame()->function()->IsJSFunction()) return false;
234 Object* script = JSFunction::cast(frame()->function())->shared()->script();
235 // Don't show functions from native scripts to user.
236 return (script->IsScript() &&
237 Script::TYPE_NATIVE != Script::cast(script)->type()->value());
238}
239
Steve Blocka7e24c12009-10-30 11:49:00 +0000240
241// -------------------------------------------------------------------------
242
243
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100244bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
245 if (!validator_.IsValid(fp)) return false;
246 Address sp = ExitFrame::ComputeStackPointer(fp);
247 if (!validator_.IsValid(sp)) return false;
248 StackFrame::State state;
249 ExitFrame::FillState(fp, sp, &state);
250 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
251 return false;
252 }
253 return *state.pc_address != NULL;
254}
255
256
Ben Murdoch8b112d22011-06-08 16:22:53 +0100257SafeStackFrameIterator::ActiveCountMaintainer::ActiveCountMaintainer(
258 Isolate* isolate)
259 : isolate_(isolate) {
260 isolate_->set_safe_stack_iterator_counter(
261 isolate_->safe_stack_iterator_counter() + 1);
262}
263
264
265SafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() {
266 isolate_->set_safe_stack_iterator_counter(
267 isolate_->safe_stack_iterator_counter() - 1);
268}
269
270
Steve Blocka7e24c12009-10-30 11:49:00 +0000271SafeStackFrameIterator::SafeStackFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100272 Isolate* isolate,
Steve Blocka7e24c12009-10-30 11:49:00 +0000273 Address fp, Address sp, Address low_bound, Address high_bound) :
Ben Murdoch8b112d22011-06-08 16:22:53 +0100274 maintainer_(isolate),
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100275 stack_validator_(low_bound, high_bound),
Steve Block44f0eee2011-05-26 01:26:41 +0100276 is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
Steve Blocka7e24c12009-10-30 11:49:00 +0000277 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
278 is_working_iterator_(is_valid_top_ || is_valid_fp_),
279 iteration_done_(!is_working_iterator_),
Steve Block44f0eee2011-05-26 01:26:41 +0100280 iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000281}
282
Ben Murdoch8b112d22011-06-08 16:22:53 +0100283bool SafeStackFrameIterator::is_active(Isolate* isolate) {
284 return isolate->safe_stack_iterator_counter() > 0;
285}
286
Steve Blocka7e24c12009-10-30 11:49:00 +0000287
Steve Block44f0eee2011-05-26 01:26:41 +0100288bool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
289 Address low_bound, Address high_bound) {
290 ThreadLocalTop* top = isolate->thread_local_top();
291 Address fp = Isolate::c_entry_fp(top);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100292 ExitFrameValidator validator(low_bound, high_bound);
293 if (!validator.IsValidFP(fp)) return false;
Steve Block44f0eee2011-05-26 01:26:41 +0100294 return Isolate::handler(top) != NULL;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100295}
296
297
Steve Blocka7e24c12009-10-30 11:49:00 +0000298void SafeStackFrameIterator::Advance() {
299 ASSERT(is_working_iterator_);
300 ASSERT(!done());
301 StackFrame* last_frame = iterator_.frame();
302 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
303 // Before advancing to the next stack frame, perform pointer validity tests
304 iteration_done_ = !IsValidFrame(last_frame) ||
305 !CanIterateHandles(last_frame, iterator_.handler()) ||
306 !IsValidCaller(last_frame);
307 if (iteration_done_) return;
308
309 iterator_.Advance();
310 if (iterator_.done()) return;
311 // Check that we have actually moved to the previous frame in the stack
312 StackFrame* prev_frame = iterator_.frame();
313 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
314}
315
316
317bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
318 StackHandler* handler) {
319 // If StackIterator iterates over StackHandles, verify that
320 // StackHandlerIterator can be instantiated (see StackHandlerIterator
321 // constructor.)
322 return !is_valid_top_ || (frame->sp() <= handler->address());
323}
324
325
326bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
327 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
328}
329
330
331bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
332 StackFrame::State state;
333 if (frame->is_entry() || frame->is_entry_construct()) {
334 // See EntryFrame::GetCallerState. It computes the caller FP address
335 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
336 // sure that caller FP address is valid.
337 Address caller_fp = Memory::Address_at(
338 frame->fp() + EntryFrameConstants::kCallerFPOffset);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100339 ExitFrameValidator validator(stack_validator_);
340 if (!validator.IsValidFP(caller_fp)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000341 } else if (frame->is_arguments_adaptor()) {
342 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
343 // the number of arguments is stored on stack as Smi. We need to check
344 // that it really an Smi.
345 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
346 GetExpression(0);
347 if (!number_of_args->IsSmi()) {
348 return false;
349 }
350 }
351 frame->ComputeCallerState(&state);
352 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
353 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
354}
355
356
357void SafeStackFrameIterator::Reset() {
358 if (is_working_iterator_) {
359 iterator_.Reset();
360 iteration_done_ = false;
361 }
362}
363
364
365// -------------------------------------------------------------------------
366
367
Steve Blocka7e24c12009-10-30 11:49:00 +0000368SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100369 Isolate* isolate,
Steve Blocka7e24c12009-10-30 11:49:00 +0000370 Address fp, Address sp, Address low_bound, Address high_bound) :
Steve Block44f0eee2011-05-26 01:26:41 +0100371 SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000372 if (!done() && !frame()->is_java_script()) Advance();
373}
374
375
376void SafeStackTraceFrameIterator::Advance() {
377 while (true) {
378 SafeJavaScriptFrameIterator::Advance();
379 if (done()) return;
380 if (frame()->is_java_script()) return;
381 }
382}
Steve Blocka7e24c12009-10-30 11:49:00 +0000383
384
Ben Murdoch8b112d22011-06-08 16:22:53 +0100385Code* StackFrame::GetSafepointData(Isolate* isolate,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100386 Address inner_pointer,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100387 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100388 unsigned* stack_slots) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100389 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
390 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100391 if (!entry->safepoint_entry.is_valid()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100392 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100393 ASSERT(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100394 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100395 ASSERT(entry->safepoint_entry.Equals(
396 entry->code->GetSafepointEntry(inner_pointer)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100397 }
398
399 // Fill in the results and return the code.
400 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100401 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100402 *stack_slots = code->stack_slots();
403 return code;
404}
405
406
Steve Blocka7e24c12009-10-30 11:49:00 +0000407bool StackFrame::HasHandler() const {
408 StackHandlerIterator it(this, top_handler());
409 return !it.done();
410}
411
Ben Murdochb0fe1622011-05-05 13:52:32 +0100412
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100413#ifdef DEBUG
414static bool GcSafeCodeContains(HeapObject* object, Address addr);
415#endif
416
417
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100418void StackFrame::IteratePc(ObjectVisitor* v,
419 Address* pc_address,
420 Code* holder) {
421 Address pc = *pc_address;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100422 ASSERT(GcSafeCodeContains(holder, pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100423 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
424 Object* code = holder;
425 v->VisitPointer(&code);
426 if (code != holder) {
427 holder = reinterpret_cast<Code*>(code);
428 pc = holder->instruction_start() + pc_offset;
429 *pc_address = pc;
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000431}
432
433
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100434void StackFrame::SetReturnAddressLocationResolver(
435 ReturnAddressLocationResolver resolver) {
436 ASSERT(return_address_location_resolver == NULL);
437 return_address_location_resolver = resolver;
438}
439
440
Ben Murdoch8b112d22011-06-08 16:22:53 +0100441StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100442 ASSERT(state->fp != NULL);
443 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
444 return ARGUMENTS_ADAPTOR;
Steve Blocka7e24c12009-10-30 11:49:00 +0000445 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100446 // The marker and function offsets overlap. If the marker isn't a
447 // smi then the frame is a JavaScript frame -- and the marker is
448 // really the function.
449 const int offset = StandardFrameConstants::kMarkerOffset;
450 Object* marker = Memory::Object_at(state->fp + offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100451 if (!marker->IsSmi()) {
452 // If we're using a "safe" stack iterator, we treat optimized
453 // frames as normal JavaScript frames to avoid having to look
454 // into the heap to determine the state. This is safe as long
455 // as nobody tries to GC...
Ben Murdoch8b112d22011-06-08 16:22:53 +0100456 if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT;
457 Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100458 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
459 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
460 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100461 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000462}
463
464
Steve Blocka7e24c12009-10-30 11:49:00 +0000465
466StackFrame::Type StackFrame::GetCallerState(State* state) const {
467 ComputeCallerState(state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100468 return ComputeType(isolate(), state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000469}
470
471
Iain Merrick75681382010-08-19 15:07:18 +0100472Code* EntryFrame::unchecked_code() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100473 return HEAP->raw_unchecked_js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000474}
475
476
477void EntryFrame::ComputeCallerState(State* state) const {
478 GetCallerState(state);
479}
480
481
Steve Block6ded16b2010-05-10 14:33:55 +0100482void EntryFrame::SetCallerFp(Address caller_fp) {
483 const int offset = EntryFrameConstants::kCallerFPOffset;
484 Memory::Address_at(this->fp() + offset) = caller_fp;
485}
486
487
Steve Blocka7e24c12009-10-30 11:49:00 +0000488StackFrame::Type EntryFrame::GetCallerState(State* state) const {
489 const int offset = EntryFrameConstants::kCallerFPOffset;
490 Address fp = Memory::Address_at(this->fp() + offset);
491 return ExitFrame::GetStateForFramePointer(fp, state);
492}
493
494
Iain Merrick75681382010-08-19 15:07:18 +0100495Code* EntryConstructFrame::unchecked_code() const {
Steve Block44f0eee2011-05-26 01:26:41 +0100496 return HEAP->raw_unchecked_js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000497}
498
499
Steve Blockd0582a62009-12-15 09:54:21 +0000500Object*& ExitFrame::code_slot() const {
501 const int offset = ExitFrameConstants::kCodeOffset;
502 return Memory::Object_at(fp() + offset);
503}
504
505
Iain Merrick75681382010-08-19 15:07:18 +0100506Code* ExitFrame::unchecked_code() const {
507 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000508}
509
510
511void ExitFrame::ComputeCallerState(State* state) const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100512 // Set up the caller state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000513 state->sp = caller_sp();
514 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100515 state->pc_address = ResolveReturnAddressLocation(
516 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
Steve Blocka7e24c12009-10-30 11:49:00 +0000517}
518
519
Steve Block6ded16b2010-05-10 14:33:55 +0100520void ExitFrame::SetCallerFp(Address caller_fp) {
521 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
522}
523
524
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100525void ExitFrame::Iterate(ObjectVisitor* v) const {
526 // The arguments are traversed as part of the expression stack of
527 // the calling frame.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100528 IteratePc(v, pc_address(), LookupCode());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100529 v->VisitPointer(&code_slot());
530}
531
532
Steve Blocka7e24c12009-10-30 11:49:00 +0000533Address ExitFrame::GetCallerStackPointer() const {
534 return fp() + ExitFrameConstants::kCallerSPDisplacement;
535}
536
537
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100538StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
539 if (fp == 0) return NONE;
540 Address sp = ComputeStackPointer(fp);
541 FillState(fp, sp, state);
542 ASSERT(*state->pc_address != NULL);
543 return EXIT;
544}
545
546
547void ExitFrame::FillState(Address fp, Address sp, State* state) {
548 state->sp = sp;
549 state->fp = fp;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100550 state->pc_address = ResolveReturnAddressLocation(
551 reinterpret_cast<Address*>(sp - 1 * kPointerSize));
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100552}
553
554
Steve Blocka7e24c12009-10-30 11:49:00 +0000555Address StandardFrame::GetExpressionAddress(int n) const {
556 const int offset = StandardFrameConstants::kExpressionsOffset;
557 return fp() + offset - n * kPointerSize;
558}
559
560
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000561Object* StandardFrame::GetExpression(Address fp, int index) {
562 return Memory::Object_at(GetExpressionAddress(fp, index));
563}
564
565
566Address StandardFrame::GetExpressionAddress(Address fp, int n) {
567 const int offset = StandardFrameConstants::kExpressionsOffset;
568 return fp + offset - n * kPointerSize;
569}
570
571
Steve Blocka7e24c12009-10-30 11:49:00 +0000572int StandardFrame::ComputeExpressionsCount() const {
573 const int offset =
574 StandardFrameConstants::kExpressionsOffset + kPointerSize;
575 Address base = fp() + offset;
576 Address limit = sp();
577 ASSERT(base >= limit); // stack grows downwards
578 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000579 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000580}
581
582
583void StandardFrame::ComputeCallerState(State* state) const {
584 state->sp = caller_sp();
585 state->fp = caller_fp();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100586 state->pc_address = ResolveReturnAddressLocation(
587 reinterpret_cast<Address*>(ComputePCAddress(fp())));
Steve Blocka7e24c12009-10-30 11:49:00 +0000588}
589
590
Steve Block6ded16b2010-05-10 14:33:55 +0100591void StandardFrame::SetCallerFp(Address caller_fp) {
592 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
593 caller_fp;
594}
595
596
Steve Blocka7e24c12009-10-30 11:49:00 +0000597bool StandardFrame::IsExpressionInsideHandler(int n) const {
598 Address address = GetExpressionAddress(n);
599 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
600 if (it.handler()->includes(address)) return true;
601 }
602 return false;
603}
604
605
Ben Murdochb0fe1622011-05-05 13:52:32 +0100606void OptimizedFrame::Iterate(ObjectVisitor* v) const {
607#ifdef DEBUG
608 // Make sure that optimized frames do not contain any stack handlers.
609 StackHandlerIterator it(this, top_handler());
610 ASSERT(it.done());
611#endif
612
613 // Make sure that we're not doing "safe" stack frame iteration. We cannot
614 // possibly find pointers in optimized frames in that state.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100615 ASSERT(!SafeStackFrameIterator::is_active(isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100616
617 // Compute the safepoint information.
618 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100619 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100620 Code* code = StackFrame::GetSafepointData(
Ben Murdoch8b112d22011-06-08 16:22:53 +0100621 isolate(), pc(), &safepoint_entry, &stack_slots);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100622 unsigned slot_space = stack_slots * kPointerSize;
623
Ben Murdoch8b112d22011-06-08 16:22:53 +0100624 // Visit the outgoing parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100625 Object** parameters_base = &Memory::Object_at(sp());
626 Object** parameters_limit = &Memory::Object_at(
627 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
628
Ben Murdochb8e0da22011-05-16 14:20:40 +0100629 // Visit the parameters that may be on top of the saved registers.
630 if (safepoint_entry.argument_count() > 0) {
631 v->VisitPointers(parameters_base,
632 parameters_base + safepoint_entry.argument_count());
633 parameters_base += safepoint_entry.argument_count();
634 }
635
636 // Skip saved double registers.
637 if (safepoint_entry.has_doubles()) {
638 parameters_base += DoubleRegister::kNumAllocatableRegisters *
639 kDoubleSize / kPointerSize;
640 }
641
Ben Murdochb0fe1622011-05-05 13:52:32 +0100642 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100643 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100644 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100645 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100646 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
647 v->VisitPointer(parameters_base + reg_stack_index);
648 }
649 }
650 // Skip the words containing the register values.
651 parameters_base += kNumSafepointRegisters;
652 }
653
654 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100655 uint8_t* safepoint_bits = safepoint_entry.bits();
656 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100657
658 // Visit the rest of the parameters.
659 v->VisitPointers(parameters_base, parameters_limit);
660
661 // Visit pointer spill slots and locals.
662 for (unsigned index = 0; index < stack_slots; index++) {
663 int byte_index = index >> kBitsPerByteLog2;
664 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100665 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100666 v->VisitPointer(parameters_limit + index);
667 }
668 }
669
670 // Visit the context and the function.
671 Object** fixed_base = &Memory::Object_at(
672 fp() + JavaScriptFrameConstants::kFunctionOffset);
673 Object** fixed_limit = &Memory::Object_at(fp());
674 v->VisitPointers(fixed_base, fixed_limit);
675
676 // Visit the return address in the callee and incoming arguments.
677 IteratePc(v, pc_address(), code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000678}
679
680
681bool JavaScriptFrame::IsConstructor() const {
682 Address fp = caller_fp();
683 if (has_adapted_arguments()) {
684 // Skip the arguments adaptor frame and look at the real caller.
685 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
686 }
687 return IsConstructFrame(fp);
688}
689
690
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000691int JavaScriptFrame::GetArgumentsLength() const {
692 // If there is an arguments adaptor frame get the arguments length from it.
693 if (has_adapted_arguments()) {
694 return Smi::cast(GetExpression(caller_fp(), 0))->value();
695 } else {
696 return GetNumberOfIncomingArguments();
697 }
698}
699
700
Iain Merrick75681382010-08-19 15:07:18 +0100701Code* JavaScriptFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000702 JSFunction* function = JSFunction::cast(this->function());
Iain Merrick75681382010-08-19 15:07:18 +0100703 return function->unchecked_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000704}
705
706
Ben Murdoch8b112d22011-06-08 16:22:53 +0100707int JavaScriptFrame::GetNumberOfIncomingArguments() const {
708 ASSERT(!SafeStackFrameIterator::is_active(isolate()) &&
709 isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
710
711 JSFunction* function = JSFunction::cast(this->function());
712 return function->shared()->formal_parameter_count();
713}
714
715
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100716Address JavaScriptFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100717 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100718}
719
720
Ben Murdochb0fe1622011-05-05 13:52:32 +0100721void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
722 ASSERT(functions->length() == 0);
723 functions->Add(JSFunction::cast(function()));
724}
725
726
727void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
728 ASSERT(functions->length() == 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100729 Code* code_pointer = LookupCode();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100730 int offset = static_cast<int>(pc() - code_pointer->address());
731 FrameSummary summary(receiver(),
732 JSFunction::cast(function()),
733 code_pointer,
734 offset,
735 IsConstructor());
736 functions->Add(summary);
737}
738
739
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100740void JavaScriptFrame::PrintTop(FILE* file,
741 bool print_args,
742 bool print_line_number) {
743 // constructor calls
744 HandleScope scope;
745 AssertNoAllocation no_allocation;
746 JavaScriptFrameIterator it;
747 while (!it.done()) {
748 if (it.frame()->is_java_script()) {
749 JavaScriptFrame* frame = it.frame();
750 if (frame->IsConstructor()) PrintF(file, "new ");
751 // function name
752 Object* maybe_fun = frame->function();
753 if (maybe_fun->IsJSFunction()) {
754 JSFunction* fun = JSFunction::cast(maybe_fun);
755 fun->PrintName();
756 Code* js_code = frame->unchecked_code();
757 Address pc = frame->pc();
758 int code_offset =
759 static_cast<int>(pc - js_code->instruction_start());
760 PrintF("+%d", code_offset);
761 SharedFunctionInfo* shared = fun->shared();
762 if (print_line_number) {
763 Code* code = Code::cast(
764 v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
765 int source_pos = code->SourcePosition(pc);
766 Object* maybe_script = shared->script();
767 if (maybe_script->IsScript()) {
768 Handle<Script> script(Script::cast(maybe_script));
769 int line = GetScriptLineNumberSafe(script, source_pos) + 1;
770 Object* script_name_raw = script->name();
771 if (script_name_raw->IsString()) {
772 String* script_name = String::cast(script->name());
773 SmartArrayPointer<char> c_script_name =
774 script_name->ToCString(DISALLOW_NULLS,
775 ROBUST_STRING_TRAVERSAL);
776 PrintF(file, " at %s:%d", *c_script_name, line);
777 } else {
778 PrintF(file, "at <unknown>:%d", line);
779 }
780 } else {
781 PrintF(file, " at <unknown>:<unknown>");
782 }
783 }
784 } else {
785 PrintF("<unknown>");
786 }
787
788 if (print_args) {
789 // function arguments
790 // (we are intentionally only printing the actually
791 // supplied parameters, not all parameters required)
792 PrintF(file, "(this=");
793 frame->receiver()->ShortPrint(file);
794 const int length = frame->ComputeParametersCount();
795 for (int i = 0; i < length; i++) {
796 PrintF(file, ", ");
797 frame->GetParameter(i)->ShortPrint(file);
798 }
799 PrintF(file, ")");
800 }
801 break;
802 }
803 it.Advance();
804 }
805}
806
807
Ben Murdochb0fe1622011-05-05 13:52:32 +0100808void FrameSummary::Print() {
809 PrintF("receiver: ");
810 receiver_->ShortPrint();
811 PrintF("\nfunction: ");
812 function_->shared()->DebugName()->ShortPrint();
813 PrintF("\ncode: ");
814 code_->ShortPrint();
815 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
816 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
817 PrintF("\npc: %d\n", offset_);
818}
819
820
821void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
822 ASSERT(frames->length() == 0);
823 ASSERT(is_optimized());
824
Steve Block1e0659c2011-05-24 12:43:12 +0100825 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100826 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
827
828 // BUG(3243555): Since we don't have a lazy-deopt registered at
829 // throw-statements, we can't use the translation at the call-site of
830 // throw. An entry with no deoptimization index indicates a call-site
831 // without a lazy-deopt. As a consequence we are not allowed to inline
832 // functions containing throw.
833 if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
834 JavaScriptFrame::Summarize(frames);
835 return;
836 }
837
838 TranslationIterator it(data->TranslationByteArray(),
839 data->TranslationIndex(deopt_index)->value());
840 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
841 ASSERT(opcode == Translation::BEGIN);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100842 it.Next(); // Drop frame count.
843 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100844
845 // We create the summary in reverse order because the frames
846 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100847 bool is_constructor = IsConstructor();
848 int i = jsframe_count;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100849 while (i > 0) {
850 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100851 if (opcode == Translation::JS_FRAME) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100852 i--;
853 int ast_id = it.Next();
854 int function_id = it.Next();
855 it.Next(); // Skip height.
856 JSFunction* function =
857 JSFunction::cast(data->LiteralArray()->get(function_id));
858
859 // The translation commands are ordered and the receiver is always
860 // at the first position. Since we are always at a call when we need
861 // to construct a stack trace, the receiver is always in a stack slot.
862 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch257744e2011-11-30 15:57:28 +0000863 ASSERT(opcode == Translation::STACK_SLOT ||
864 opcode == Translation::LITERAL);
865 int index = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100866
867 // Get the correct receiver in the optimized frame.
868 Object* receiver = NULL;
Ben Murdoch257744e2011-11-30 15:57:28 +0000869 if (opcode == Translation::LITERAL) {
870 receiver = data->LiteralArray()->get(index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100871 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +0000872 // Positive index means the value is spilled to the locals
873 // area. Negative means it is stored in the incoming parameter
874 // area.
875 if (index >= 0) {
876 receiver = GetExpression(index);
877 } else {
878 // Index -1 overlaps with last parameter, -n with the first parameter,
879 // (-n - 1) with the receiver with n being the number of parameters
880 // of the outermost, optimized frame.
881 int parameter_count = ComputeParametersCount();
882 int parameter_index = index + parameter_count;
883 receiver = (parameter_index == -1)
884 ? this->receiver()
885 : this->GetParameter(parameter_index);
886 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100887 }
888
889 Code* code = function->shared()->code();
890 DeoptimizationOutputData* output_data =
891 DeoptimizationOutputData::cast(code->deoptimization_data());
892 unsigned entry = Deoptimizer::GetOutputInfo(output_data,
893 ast_id,
894 function->shared());
895 unsigned pc_offset =
896 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
897 ASSERT(pc_offset > 0);
898
899 FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
900 frames->Add(summary);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100901 is_constructor = false;
902 } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) {
903 // The next encountered JS_FRAME will be marked as a constructor call.
904 it.Skip(Translation::NumberOfOperandsFor(opcode));
905 ASSERT(!is_constructor);
906 is_constructor = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100907 } else {
908 // Skip over operands to advance to the next opcode.
909 it.Skip(Translation::NumberOfOperandsFor(opcode));
910 }
911 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100912 ASSERT(!is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100913}
914
915
916DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
917 int* deopt_index) {
918 ASSERT(is_optimized());
919
920 JSFunction* opt_function = JSFunction::cast(function());
921 Code* code = opt_function->code();
922
923 // The code object may have been replaced by lazy deoptimization. Fall
924 // back to a slow search in this case to find the original optimized
925 // code object.
926 if (!code->contains(pc())) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100927 code = isolate()->inner_pointer_to_code_cache()->
928 GcSafeFindCodeForInnerPointer(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100929 }
930 ASSERT(code != NULL);
931 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
932
Ben Murdochb8e0da22011-05-16 14:20:40 +0100933 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
934 *deopt_index = safepoint_entry.deoptimization_index();
Steve Block1e0659c2011-05-24 12:43:12 +0100935 ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100936
937 return DeoptimizationInputData::cast(code->deoptimization_data());
938}
939
940
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000941int OptimizedFrame::GetInlineCount() {
942 ASSERT(is_optimized());
943
944 int deopt_index = Safepoint::kNoDeoptimizationIndex;
945 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
946
947 TranslationIterator it(data->TranslationByteArray(),
948 data->TranslationIndex(deopt_index)->value());
949 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
950 ASSERT(opcode == Translation::BEGIN);
951 USE(opcode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100952 it.Next(); // Drop frame count.
953 int jsframe_count = it.Next();
954 return jsframe_count;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000955}
956
957
Ben Murdochb0fe1622011-05-05 13:52:32 +0100958void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
959 ASSERT(functions->length() == 0);
960 ASSERT(is_optimized());
961
Steve Block1e0659c2011-05-24 12:43:12 +0100962 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100963 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
964
965 TranslationIterator it(data->TranslationByteArray(),
966 data->TranslationIndex(deopt_index)->value());
967 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
968 ASSERT(opcode == Translation::BEGIN);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100969 it.Next(); // Drop frame count.
970 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100971
972 // We insert the frames in reverse order because the frames
973 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100974 while (jsframe_count > 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100975 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100976 if (opcode == Translation::JS_FRAME) {
977 jsframe_count--;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100978 it.Next(); // Skip ast id.
979 int function_id = it.Next();
980 it.Next(); // Skip height.
981 JSFunction* function =
982 JSFunction::cast(data->LiteralArray()->get(function_id));
983 functions->Add(function);
984 } else {
985 // Skip over operands to advance to the next opcode.
986 it.Skip(Translation::NumberOfOperandsFor(opcode));
987 }
988 }
989}
990
991
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100992int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
993 return Smi::cast(GetExpression(0))->value();
994}
995
996
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100997Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100998 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100999}
1000
1001
1002Address InternalFrame::GetCallerStackPointer() const {
1003 // Internal frames have no arguments. The stack pointer of the
1004 // caller is at a fixed offset from the frame pointer.
1005 return fp() + StandardFrameConstants::kCallerSPOffset;
1006}
1007
1008
Iain Merrick75681382010-08-19 15:07:18 +01001009Code* ArgumentsAdaptorFrame::unchecked_code() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001010 return isolate()->builtins()->builtin(
Steve Block44f0eee2011-05-26 01:26:41 +01001011 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +00001012}
1013
1014
Iain Merrick75681382010-08-19 15:07:18 +01001015Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 const int offset = InternalFrameConstants::kCodeOffset;
1017 Object* code = Memory::Object_at(fp() + offset);
1018 ASSERT(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +01001019 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001020}
1021
1022
1023void StackFrame::PrintIndex(StringStream* accumulator,
1024 PrintMode mode,
1025 int index) {
1026 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1027}
1028
1029
1030void JavaScriptFrame::Print(StringStream* accumulator,
1031 PrintMode mode,
1032 int index) const {
1033 HandleScope scope;
1034 Object* receiver = this->receiver();
1035 Object* function = this->function();
1036
1037 accumulator->PrintSecurityTokenIfChanged(function);
1038 PrintIndex(accumulator, mode, index);
1039 Code* code = NULL;
1040 if (IsConstructor()) accumulator->Add("new ");
1041 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +01001042
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001043 // Get scope information for nicer output, if possible. If code is NULL, or
1044 // doesn't contain scope info, scope_info will return 0 for the number of
1045 // parameters, stack local variables, context local variables, stack slots,
1046 // or context slots.
1047 Handle<ScopeInfo> scope_info(ScopeInfo::Empty());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001048
Steve Block6ded16b2010-05-10 14:33:55 +01001049 if (function->IsJSFunction()) {
1050 Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001051 scope_info = Handle<ScopeInfo>(shared->scope_info());
Steve Block6ded16b2010-05-10 14:33:55 +01001052 Object* script_obj = shared->script();
1053 if (script_obj->IsScript()) {
1054 Handle<Script> script(Script::cast(script_obj));
1055 accumulator->Add(" [");
1056 accumulator->PrintName(script->name());
1057
1058 Address pc = this->pc();
1059 if (code != NULL && code->kind() == Code::FUNCTION &&
Leon Clarkeac952652010-07-15 11:15:24 +01001060 pc >= code->instruction_start() && pc < code->instruction_end()) {
Steve Block6ded16b2010-05-10 14:33:55 +01001061 int source_pos = code->SourcePosition(pc);
1062 int line = GetScriptLineNumberSafe(script, source_pos) + 1;
1063 accumulator->Add(":%d", line);
1064 } else {
1065 int function_start_pos = shared->start_position();
1066 int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
1067 accumulator->Add(":~%d", line);
1068 }
1069
1070 accumulator->Add("] ");
1071 }
1072 }
1073
Steve Blocka7e24c12009-10-30 11:49:00 +00001074 accumulator->Add("(this=%o", receiver);
1075
Steve Blocka7e24c12009-10-30 11:49:00 +00001076 // Print the parameters.
1077 int parameters_count = ComputeParametersCount();
1078 for (int i = 0; i < parameters_count; i++) {
1079 accumulator->Add(",");
1080 // If we have a name for the parameter we print it. Nameless
1081 // parameters are either because we have more actual parameters
1082 // than formal parameters or because we have no scope information.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001083 if (i < scope_info->ParameterCount()) {
1084 accumulator->PrintName(scope_info->ParameterName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001085 accumulator->Add("=");
1086 }
1087 accumulator->Add("%o", GetParameter(i));
1088 }
1089
1090 accumulator->Add(")");
1091 if (mode == OVERVIEW) {
1092 accumulator->Add("\n");
1093 return;
1094 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001095 if (is_optimized()) {
1096 accumulator->Add(" {\n// optimized frame\n}\n");
1097 return;
1098 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001099 accumulator->Add(" {\n");
1100
1101 // Compute the number of locals and expression stack elements.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001102 int stack_locals_count = scope_info->StackLocalCount();
1103 int heap_locals_count = scope_info->ContextLocalCount();
Steve Blocka7e24c12009-10-30 11:49:00 +00001104 int expressions_count = ComputeExpressionsCount();
1105
1106 // Print stack-allocated local variables.
1107 if (stack_locals_count > 0) {
1108 accumulator->Add(" // stack-allocated locals\n");
1109 }
1110 for (int i = 0; i < stack_locals_count; i++) {
1111 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001112 accumulator->PrintName(scope_info->StackLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001113 accumulator->Add(" = ");
1114 if (i < expressions_count) {
1115 accumulator->Add("%o", GetExpression(i));
1116 } else {
1117 accumulator->Add("// no expression found - inconsistent frame?");
1118 }
1119 accumulator->Add("\n");
1120 }
1121
1122 // Try to get hold of the context of this frame.
1123 Context* context = NULL;
1124 if (this->context() != NULL && this->context()->IsContext()) {
1125 context = Context::cast(this->context());
1126 }
1127
1128 // Print heap-allocated local variables.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001129 if (heap_locals_count > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001130 accumulator->Add(" // heap-allocated locals\n");
1131 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001132 for (int i = 0; i < heap_locals_count; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001133 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001134 accumulator->PrintName(scope_info->ContextLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001135 accumulator->Add(" = ");
1136 if (context != NULL) {
1137 if (i < context->length()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001138 accumulator->Add("%o", context->get(Context::MIN_CONTEXT_SLOTS + i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001139 } else {
1140 accumulator->Add(
1141 "// warning: missing context slot - inconsistent frame?");
1142 }
1143 } else {
1144 accumulator->Add("// warning: no context found - inconsistent frame?");
1145 }
1146 accumulator->Add("\n");
1147 }
1148
1149 // Print the expression stack.
1150 int expressions_start = stack_locals_count;
1151 if (expressions_start < expressions_count) {
1152 accumulator->Add(" // expression stack (top to bottom)\n");
1153 }
1154 for (int i = expressions_count - 1; i >= expressions_start; i--) {
1155 if (IsExpressionInsideHandler(i)) continue;
1156 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1157 }
1158
1159 // Print details about the function.
1160 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1161 SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
1162 accumulator->Add("--------- s o u r c e c o d e ---------\n");
1163 shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
1164 accumulator->Add("\n-----------------------------------------\n");
1165 }
1166
1167 accumulator->Add("}\n\n");
1168}
1169
1170
1171void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1172 PrintMode mode,
1173 int index) const {
1174 int actual = ComputeParametersCount();
1175 int expected = -1;
1176 Object* function = this->function();
1177 if (function->IsJSFunction()) {
1178 expected = JSFunction::cast(function)->shared()->formal_parameter_count();
1179 }
1180
1181 PrintIndex(accumulator, mode, index);
1182 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1183 if (mode == OVERVIEW) {
1184 accumulator->Add("\n");
1185 return;
1186 }
1187 accumulator->Add(" {\n");
1188
1189 // Print actual arguments.
1190 if (actual > 0) accumulator->Add(" // actual arguments\n");
1191 for (int i = 0; i < actual; i++) {
1192 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1193 if (expected != -1 && i >= expected) {
1194 accumulator->Add(" // not passed to callee");
1195 }
1196 accumulator->Add("\n");
1197 }
1198
1199 accumulator->Add("}\n\n");
1200}
1201
1202
1203void EntryFrame::Iterate(ObjectVisitor* v) const {
1204 StackHandlerIterator it(this, top_handler());
1205 ASSERT(!it.done());
1206 StackHandler* handler = it.handler();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001207 ASSERT(handler->is_js_entry());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001208 handler->Iterate(v, LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001209#ifdef DEBUG
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001210 // Make sure that the entry frame does not contain more than one
1211 // stack handler.
Steve Blocka7e24c12009-10-30 11:49:00 +00001212 it.Advance();
1213 ASSERT(it.done());
1214#endif
Ben Murdoch8b112d22011-06-08 16:22:53 +01001215 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001216}
1217
1218
1219void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
1220 const int offset = StandardFrameConstants::kContextOffset;
1221 Object** base = &Memory::Object_at(sp());
1222 Object** limit = &Memory::Object_at(fp() + offset) + 1;
1223 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1224 StackHandler* handler = it.handler();
1225 // Traverse pointers down to - but not including - the next
1226 // handler in the handler chain. Update the base to skip the
1227 // handler and allow the handler to traverse its own pointers.
1228 const Address address = handler->address();
1229 v->VisitPointers(base, reinterpret_cast<Object**>(address));
1230 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1231 // Traverse the pointers in the handler itself.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001232 handler->Iterate(v, LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001233 }
1234 v->VisitPointers(base, limit);
1235}
1236
1237
1238void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1239 IterateExpressions(v);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001240 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001241}
1242
1243
1244void InternalFrame::Iterate(ObjectVisitor* v) const {
1245 // Internal frames only have object pointers on the expression stack
1246 // as they never have any arguments.
1247 IterateExpressions(v);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001248 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001249}
1250
1251
1252// -------------------------------------------------------------------------
1253
1254
1255JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
1256 ASSERT(n >= 0);
1257 for (int i = 0; i <= n; i++) {
1258 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1259 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1260 iterator_.Advance();
1261 }
1262 UNREACHABLE();
1263 return NULL;
1264}
1265
1266
1267// -------------------------------------------------------------------------
1268
1269
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001270static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1271 MapWord map_word = object->map_word();
1272 return map_word.IsForwardingAddress() ?
1273 map_word.ToForwardingAddress()->map() : map_word.ToMap();
1274}
1275
1276
1277static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1278 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1279}
1280
1281
1282#ifdef DEBUG
1283static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1284 Map* map = GcSafeMapOfCodeSpaceObject(code);
1285 ASSERT(map == code->GetHeap()->code_map());
1286 Address start = code->address();
1287 Address end = code->address() + code->SizeFromMap(map);
1288 return start <= addr && addr < end;
1289}
1290#endif
1291
1292
1293Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1294 Address inner_pointer) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001295 Code* code = reinterpret_cast<Code*>(object);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001296 ASSERT(code != NULL && GcSafeCodeContains(code, inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001297 return code;
1298}
1299
1300
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001301Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1302 Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001303 Heap* heap = isolate_->heap();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001304 // Check if the inner pointer points into a large object chunk.
1305 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1306 if (large_page != NULL) {
1307 return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1308 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001309
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001310 // Iterate through the page until we reach the end or find an object starting
1311 // after the inner pointer.
1312 Page* page = Page::FromAddress(inner_pointer);
1313
1314 Address addr = page->skip_list()->StartFor(inner_pointer);
1315
1316 Address top = heap->code_space()->top();
1317 Address limit = heap->code_space()->limit();
1318
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001319 while (true) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001320 if (addr == top && addr != limit) {
1321 addr = limit;
1322 continue;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001323 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001324
1325 HeapObject* obj = HeapObject::FromAddress(addr);
1326 int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1327 Address next_addr = addr + obj_size;
1328 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1329 addr = next_addr;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001330 }
1331}
1332
Ben Murdochb0fe1622011-05-05 13:52:32 +01001333
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001334InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1335 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001336 isolate_->counters()->pc_to_code()->Increment();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001337 ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001338 uint32_t hash = ComputeIntegerHash(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001339 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)),
Ben Murdochc7cc0282012-03-05 14:35:55 +00001340 v8::internal::kZeroHashSeed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001341 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1342 InnerPointerToCodeCacheEntry* entry = cache(index);
1343 if (entry->inner_pointer == inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001344 isolate_->counters()->pc_to_code_cached()->Increment();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001345 ASSERT(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001346 } else {
1347 // Because this code may be interrupted by a profiling signal that
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001348 // also queries the cache, we cannot update inner_pointer before the code
1349 // has been set. Otherwise, we risk trying to use a cache entry before
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001350 // the code has been computed.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001351 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001352 entry->safepoint_entry.Reset();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001353 entry->inner_pointer = inner_pointer;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001354 }
1355 return entry;
1356}
1357
1358
1359// -------------------------------------------------------------------------
1360
Steve Blocka7e24c12009-10-30 11:49:00 +00001361int NumRegs(RegList reglist) {
1362 int n = 0;
1363 while (reglist != 0) {
1364 n++;
1365 reglist &= reglist - 1; // clear one bit
1366 }
1367 return n;
1368}
1369
1370
Steve Block44f0eee2011-05-26 01:26:41 +01001371struct JSCallerSavedCodeData {
1372 JSCallerSavedCodeData() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001373 int i = 0;
1374 for (int r = 0; r < kNumRegs; r++)
1375 if ((kJSCallerSaved & (1 << r)) != 0)
1376 reg_code[i++] = r;
1377
1378 ASSERT(i == kNumJSCallerSaved);
1379 }
Steve Block44f0eee2011-05-26 01:26:41 +01001380 int reg_code[kNumJSCallerSaved];
1381};
1382
1383
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001384static LazyInstance<JSCallerSavedCodeData>::type caller_saved_code_data =
1385 LAZY_INSTANCE_INITIALIZER;
Steve Block44f0eee2011-05-26 01:26:41 +01001386
1387int JSCallerSavedCode(int n) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001388 ASSERT(0 <= n && n < kNumJSCallerSaved);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001389 return caller_saved_code_data.Get().reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001390}
1391
1392
Steve Block6ded16b2010-05-10 14:33:55 +01001393#define DEFINE_WRAPPER(type, field) \
1394class field##_Wrapper : public ZoneObject { \
1395 public: /* NOLINT */ \
1396 field##_Wrapper(const field& original) : frame_(original) { \
1397 } \
1398 field frame_; \
1399};
1400STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1401#undef DEFINE_WRAPPER
1402
1403static StackFrame* AllocateFrameCopy(StackFrame* frame) {
1404#define FRAME_TYPE_CASE(type, field) \
1405 case StackFrame::type: { \
1406 field##_Wrapper* wrapper = \
1407 new field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
1408 return &wrapper->frame_; \
1409 }
1410
1411 switch (frame->type()) {
1412 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1413 default: UNREACHABLE();
1414 }
1415#undef FRAME_TYPE_CASE
1416 return NULL;
1417}
1418
1419Vector<StackFrame*> CreateStackMap() {
1420 ZoneList<StackFrame*> list(10);
1421 for (StackFrameIterator it; !it.done(); it.Advance()) {
1422 StackFrame* frame = AllocateFrameCopy(it.frame());
1423 list.Add(frame);
1424 }
1425 return list.ToVector();
1426}
1427
1428
Steve Blocka7e24c12009-10-30 11:49:00 +00001429} } // namespace v8::internal