blob: 0ba8ea0020ed379dc2d70fe423b6ac00d983f6f1 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/frames.h"
6
7#include <sstream>
8
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000010
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/ast.h"
12#include "src/base/bits.h"
13#include "src/deoptimizer.h"
14#include "src/frames-inl.h"
15#include "src/full-codegen.h"
16#include "src/heap/mark-compact.h"
17#include "src/safepoint-table.h"
18#include "src/scopeinfo.h"
19#include "src/string-stream.h"
20#include "src/vm-state-inl.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000021
Steve Blocka7e24c12009-10-30 11:49:00 +000022namespace v8 {
23namespace internal {
24
Ben Murdoch3ef787d2012-04-12 10:51:47 +010025
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026ReturnAddressLocationResolver
27 StackFrame::return_address_location_resolver_ = NULL;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010028
29
Steve Blocka7e24c12009-10-30 11:49:00 +000030// Iterator that supports traversing the stack handlers of a
31// particular frame. Needs to know the top of the handler chain.
32class StackHandlerIterator BASE_EMBEDDED {
33 public:
34 StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
35 : limit_(frame->fp()), handler_(handler) {
36 // Make sure the handler has already been unwound to this frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037 DCHECK(frame->sp() <= handler->address());
Steve Blocka7e24c12009-10-30 11:49:00 +000038 }
39
40 StackHandler* handler() const { return handler_; }
41
42 bool done() {
43 return handler_ == NULL || handler_->address() > limit_;
44 }
45 void Advance() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +000047 handler_ = handler_->next();
48 }
49
50 private:
51 const Address limit_;
52 StackHandler* handler_;
53};
54
55
56// -------------------------------------------------------------------------
57
58
59#define INITIALIZE_SINGLETON(type, field) field##_(this),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000060StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
61 bool can_access_heap_objects)
Ben Murdoch8b112d22011-06-08 16:22:53 +010062 : isolate_(isolate),
63 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
64 frame_(NULL), handler_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065 can_access_heap_objects_(can_access_heap_objects) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010066}
Steve Blocka7e24c12009-10-30 11:49:00 +000067#undef INITIALIZE_SINGLETON
68
69
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070StackFrameIterator::StackFrameIterator(Isolate* isolate)
71 : StackFrameIteratorBase(isolate, true) {
72 Reset(isolate->thread_local_top());
73}
74
75
76StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
77 : StackFrameIteratorBase(isolate, true) {
78 Reset(t);
79}
80
81
82void StackFrameIterator::Advance() {
83 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +000084 // Compute the state of the calling frame before restoring
85 // callee-saved registers and unwinding handlers. This allows the
86 // frame code that computes the caller state to access the top
87 // handler and the value of any callee-saved register if needed.
88 StackFrame::State state;
89 StackFrame::Type type = frame_->GetCallerState(&state);
90
91 // Unwind handlers corresponding to the current frame.
92 StackHandlerIterator it(frame_, handler_);
93 while (!it.done()) it.Advance();
94 handler_ = it.handler();
95
96 // Advance to the calling frame.
97 frame_ = SingletonFor(type, &state);
98
99 // When we're done iterating over the stack frames, the handler
100 // chain must have been completely unwound.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101 DCHECK(!done() || handler_ == NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000102}
103
104
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105void StackFrameIterator::Reset(ThreadLocalTop* top) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000106 StackFrame::State state;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 StackFrame::Type type = ExitFrame::GetStateForFramePointer(
108 Isolate::c_entry_fp(top), &state);
109 handler_ = StackHandler::FromAddress(Isolate::handler(top));
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100110 if (SingletonFor(type) == NULL) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000111 frame_ = SingletonFor(type, &state);
112}
113
114
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
Steve Blocka7e24c12009-10-30 11:49:00 +0000116 StackFrame::State* state) {
117 if (type == StackFrame::NONE) return NULL;
118 StackFrame* result = SingletonFor(type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119 DCHECK(result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000120 result->state_ = *state;
121 return result;
122}
123
124
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000126#define FRAME_TYPE_CASE(type, field) \
127 case StackFrame::type: result = &field##_; break;
128
129 StackFrame* result = NULL;
130 switch (type) {
131 case StackFrame::NONE: return NULL;
132 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
133 default: break;
134 }
135 return result;
136
137#undef FRAME_TYPE_CASE
138}
139
140
141// -------------------------------------------------------------------------
142
143
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144JavaScriptFrameIterator::JavaScriptFrameIterator(
145 Isolate* isolate, StackFrame::Id id)
146 : iterator_(isolate) {
147 while (!done()) {
148 Advance();
149 if (frame()->id() == id) return;
150 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000151}
152
153
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154void JavaScriptFrameIterator::Advance() {
155 do {
156 iterator_.Advance();
157 } while (!iterator_.done() && !iterator_.frame()->is_java_script());
158}
159
160
161void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
162 if (!frame()->has_adapted_arguments()) return;
163 iterator_.Advance();
164 DCHECK(iterator_.frame()->is_arguments_adaptor());
165}
166
167
168// -------------------------------------------------------------------------
169
170
Ben Murdoch8b112d22011-06-08 16:22:53 +0100171StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
172 : JavaScriptFrameIterator(isolate) {
173 if (!done() && !IsValidFrame()) Advance();
174}
175
176
Steve Blocka7e24c12009-10-30 11:49:00 +0000177void StackTraceFrameIterator::Advance() {
178 while (true) {
179 JavaScriptFrameIterator::Advance();
180 if (done()) return;
Leon Clarke4515c472010-02-03 11:58:03 +0000181 if (IsValidFrame()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 }
183}
184
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185
Leon Clarke4515c472010-02-03 11:58:03 +0000186bool StackTraceFrameIterator::IsValidFrame() {
187 if (!frame()->function()->IsJSFunction()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 Object* script = frame()->function()->shared()->script();
Leon Clarke4515c472010-02-03 11:58:03 +0000189 // Don't show functions from native scripts to user.
190 return (script->IsScript() &&
191 Script::TYPE_NATIVE != Script::cast(script)->type()->value());
192}
193
Steve Blocka7e24c12009-10-30 11:49:00 +0000194
195// -------------------------------------------------------------------------
196
197
198SafeStackFrameIterator::SafeStackFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100199 Isolate* isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 Address fp, Address sp, Address js_entry_sp)
201 : StackFrameIteratorBase(isolate, false),
202 low_bound_(sp),
203 high_bound_(js_entry_sp),
204 top_frame_type_(StackFrame::NONE),
205 external_callback_scope_(isolate->external_callback_scope()) {
206 StackFrame::State state;
207 StackFrame::Type type;
Steve Block44f0eee2011-05-26 01:26:41 +0100208 ThreadLocalTop* top = isolate->thread_local_top();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 if (IsValidTop(top)) {
210 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
211 top_frame_type_ = type;
212 } else if (IsValidStackAddress(fp)) {
213 DCHECK(fp != NULL);
214 state.fp = fp;
215 state.sp = sp;
216 state.pc_address = StackFrame::ResolveReturnAddressLocation(
217 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
218 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
219 // we check only that kMarkerOffset is within the stack bounds and do
220 // compile time check that kContextOffset slot is pushed on the stack before
221 // kMarkerOffset.
222 STATIC_ASSERT(StandardFrameConstants::kMarkerOffset <
223 StandardFrameConstants::kContextOffset);
224 Address frame_marker = fp + StandardFrameConstants::kMarkerOffset;
225 if (IsValidStackAddress(frame_marker)) {
226 type = StackFrame::ComputeType(this, &state);
227 top_frame_type_ = type;
228 } else {
229 // Mark the frame as JAVA_SCRIPT if we cannot determine its type.
230 // The frame anyways will be skipped.
231 type = StackFrame::JAVA_SCRIPT;
232 // Top frame is incomplete so we cannot reliably determine its type.
233 top_frame_type_ = StackFrame::NONE;
234 }
235 } else {
236 return;
237 }
238 if (SingletonFor(type) == NULL) return;
239 frame_ = SingletonFor(type, &state);
240 if (frame_ == NULL) return;
241
242 Advance();
243
244 if (frame_ != NULL && !frame_->is_exit() &&
245 external_callback_scope_ != NULL &&
246 external_callback_scope_->scope_address() < frame_->fp()) {
247 // Skip top ExternalCallbackScope if we already advanced to a JS frame
248 // under it. Sampler will anyways take this top external callback.
249 external_callback_scope_ = external_callback_scope_->previous();
250 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100251}
252
253
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
255 Address c_entry_fp = Isolate::c_entry_fp(top);
256 if (!IsValidExitFrame(c_entry_fp)) return false;
257 // There should be at least one JS_ENTRY stack handler.
258 Address handler = Isolate::handler(top);
259 if (handler == NULL) return false;
260 // Check that there are no js frames on top of the native frames.
261 return c_entry_fp < handler;
262}
263
264
265void SafeStackFrameIterator::AdvanceOneFrame() {
266 DCHECK(!done());
267 StackFrame* last_frame = frame_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000268 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 // Before advancing to the next stack frame, perform pointer validity tests.
270 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
271 frame_ = NULL;
272 return;
273 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000274
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 // Advance to the previous frame.
276 StackFrame::State state;
277 StackFrame::Type type = frame_->GetCallerState(&state);
278 frame_ = SingletonFor(type, &state);
279 if (frame_ == NULL) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000280
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 // Check that we have actually moved to the previous frame in the stack.
282 if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
283 frame_ = NULL;
284 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000285}
286
287
288bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
289 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
290}
291
292
293bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
294 StackFrame::State state;
295 if (frame->is_entry() || frame->is_entry_construct()) {
296 // See EntryFrame::GetCallerState. It computes the caller FP address
297 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
298 // sure that caller FP address is valid.
299 Address caller_fp = Memory::Address_at(
300 frame->fp() + EntryFrameConstants::kCallerFPOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301 if (!IsValidExitFrame(caller_fp)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000302 } else if (frame->is_arguments_adaptor()) {
303 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
304 // the number of arguments is stored on stack as Smi. We need to check
305 // that it really an Smi.
306 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
307 GetExpression(0);
308 if (!number_of_args->IsSmi()) {
309 return false;
310 }
311 }
312 frame->ComputeCallerState(&state);
313 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000314 SingletonFor(frame->GetCallerState(&state)) != NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000315}
316
317
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000318bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
319 if (!IsValidStackAddress(fp)) return false;
320 Address sp = ExitFrame::ComputeStackPointer(fp);
321 if (!IsValidStackAddress(sp)) return false;
322 StackFrame::State state;
323 ExitFrame::FillState(fp, sp, &state);
324 if (!IsValidStackAddress(reinterpret_cast<Address>(state.pc_address))) {
325 return false;
326 }
327 return *state.pc_address != NULL;
328}
329
330
331void SafeStackFrameIterator::Advance() {
332 while (true) {
333 AdvanceOneFrame();
334 if (done()) return;
335 if (frame_->is_java_script()) return;
336 if (frame_->is_exit() && external_callback_scope_) {
337 // Some of the EXIT frames may have ExternalCallbackScope allocated on
338 // top of them. In that case the scope corresponds to the first EXIT
339 // frame beneath it. There may be other EXIT frames on top of the
340 // ExternalCallbackScope, just skip them as we cannot collect any useful
341 // information about them.
342 if (external_callback_scope_->scope_address() < frame_->fp()) {
343 Address* callback_address =
344 external_callback_scope_->callback_address();
345 if (*callback_address != NULL) {
346 frame_->state_.pc_address = callback_address;
347 }
348 external_callback_scope_ = external_callback_scope_->previous();
349 DCHECK(external_callback_scope_ == NULL ||
350 external_callback_scope_->scope_address() > frame_->fp());
351 return;
352 }
353 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000354 }
355}
356
357
358// -------------------------------------------------------------------------
359
360
Ben Murdoch8b112d22011-06-08 16:22:53 +0100361Code* StackFrame::GetSafepointData(Isolate* isolate,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100362 Address inner_pointer,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100363 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100364 unsigned* stack_slots) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100365 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
366 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100367 if (!entry->safepoint_entry.is_valid()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100368 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 DCHECK(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100370 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 DCHECK(entry->safepoint_entry.Equals(
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100372 entry->code->GetSafepointEntry(inner_pointer)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100373 }
374
375 // Fill in the results and return the code.
376 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100377 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100378 *stack_slots = code->stack_slots();
379 return code;
380}
381
382
Steve Blocka7e24c12009-10-30 11:49:00 +0000383bool StackFrame::HasHandler() const {
384 StackHandlerIterator it(this, top_handler());
385 return !it.done();
386}
387
Ben Murdochb0fe1622011-05-05 13:52:32 +0100388
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100389#ifdef DEBUG
390static bool GcSafeCodeContains(HeapObject* object, Address addr);
391#endif
392
393
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100394void StackFrame::IteratePc(ObjectVisitor* v,
395 Address* pc_address,
396 Code* holder) {
397 Address pc = *pc_address;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 DCHECK(GcSafeCodeContains(holder, pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100399 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
400 Object* code = holder;
401 v->VisitPointer(&code);
402 if (code != holder) {
403 holder = reinterpret_cast<Code*>(code);
404 pc = holder->instruction_start() + pc_offset;
405 *pc_address = pc;
Steve Blocka7e24c12009-10-30 11:49:00 +0000406 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000407}
408
409
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100410void StackFrame::SetReturnAddressLocationResolver(
411 ReturnAddressLocationResolver resolver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000412 DCHECK(return_address_location_resolver_ == NULL);
413 return_address_location_resolver_ = resolver;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100414}
415
416
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
418 State* state) {
419 DCHECK(state->fp != NULL);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100420 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
421 return ARGUMENTS_ADAPTOR;
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100423 // The marker and function offsets overlap. If the marker isn't a
424 // smi then the frame is a JavaScript frame -- and the marker is
425 // really the function.
426 const int offset = StandardFrameConstants::kMarkerOffset;
427 Object* marker = Memory::Object_at(state->fp + offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100428 if (!marker->IsSmi()) {
429 // If we're using a "safe" stack iterator, we treat optimized
430 // frames as normal JavaScript frames to avoid having to look
431 // into the heap to determine the state. This is safe as long
432 // as nobody tries to GC...
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 if (!iterator->can_access_heap_objects_) return JAVA_SCRIPT;
434 Code::Kind kind = GetContainingCode(iterator->isolate(),
435 *(state->pc_address))->kind();
436 DCHECK(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100437 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
438 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100439 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000440}
441
442
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443#ifdef DEBUG
444bool StackFrame::can_access_heap_objects() const {
445 return iterator_->can_access_heap_objects_;
446}
447#endif
448
Steve Blocka7e24c12009-10-30 11:49:00 +0000449
450StackFrame::Type StackFrame::GetCallerState(State* state) const {
451 ComputeCallerState(state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452 return ComputeType(iterator_, state);
453}
454
455
456Address StackFrame::UnpaddedFP() const {
457#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
458 if (!is_optimized()) return fp();
459 int32_t alignment_state = Memory::int32_at(
460 fp() + JavaScriptFrameConstants::kDynamicAlignmentStateOffset);
461
462 return (alignment_state == kAlignmentPaddingPushed) ?
463 (fp() + kPointerSize) : fp();
464#else
465 return fp();
466#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000467}
468
469
Iain Merrick75681382010-08-19 15:07:18 +0100470Code* EntryFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000471 return isolate()->heap()->js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000472}
473
474
475void EntryFrame::ComputeCallerState(State* state) const {
476 GetCallerState(state);
477}
478
479
Steve Block6ded16b2010-05-10 14:33:55 +0100480void EntryFrame::SetCallerFp(Address caller_fp) {
481 const int offset = EntryFrameConstants::kCallerFPOffset;
482 Memory::Address_at(this->fp() + offset) = caller_fp;
483}
484
485
Steve Blocka7e24c12009-10-30 11:49:00 +0000486StackFrame::Type EntryFrame::GetCallerState(State* state) const {
487 const int offset = EntryFrameConstants::kCallerFPOffset;
488 Address fp = Memory::Address_at(this->fp() + offset);
489 return ExitFrame::GetStateForFramePointer(fp, state);
490}
491
492
Iain Merrick75681382010-08-19 15:07:18 +0100493Code* EntryConstructFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 return isolate()->heap()->js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000495}
496
497
Steve Blockd0582a62009-12-15 09:54:21 +0000498Object*& ExitFrame::code_slot() const {
499 const int offset = ExitFrameConstants::kCodeOffset;
500 return Memory::Object_at(fp() + offset);
501}
502
503
Iain Merrick75681382010-08-19 15:07:18 +0100504Code* ExitFrame::unchecked_code() const {
505 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000506}
507
508
509void ExitFrame::ComputeCallerState(State* state) const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100510 // Set up the caller state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 state->sp = caller_sp();
512 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100513 state->pc_address = ResolveReturnAddressLocation(
514 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000515 if (FLAG_enable_ool_constant_pool) {
516 state->constant_pool_address = reinterpret_cast<Address*>(
517 fp() + ExitFrameConstants::kConstantPoolOffset);
518 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000519}
520
521
Steve Block6ded16b2010-05-10 14:33:55 +0100522void ExitFrame::SetCallerFp(Address caller_fp) {
523 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
524}
525
526
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100527void ExitFrame::Iterate(ObjectVisitor* v) const {
528 // The arguments are traversed as part of the expression stack of
529 // the calling frame.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100530 IteratePc(v, pc_address(), LookupCode());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100531 v->VisitPointer(&code_slot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 if (FLAG_enable_ool_constant_pool) {
533 v->VisitPointer(&constant_pool_slot());
534 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100535}
536
537
Steve Blocka7e24c12009-10-30 11:49:00 +0000538Address ExitFrame::GetCallerStackPointer() const {
539 return fp() + ExitFrameConstants::kCallerSPDisplacement;
540}
541
542
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100543StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
544 if (fp == 0) return NONE;
545 Address sp = ComputeStackPointer(fp);
546 FillState(fp, sp, state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 DCHECK(*state->pc_address != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100548 return EXIT;
549}
550
551
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552Address ExitFrame::ComputeStackPointer(Address fp) {
553 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
554}
555
556
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100557void ExitFrame::FillState(Address fp, Address sp, State* state) {
558 state->sp = sp;
559 state->fp = fp;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100560 state->pc_address = ResolveReturnAddressLocation(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000561 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
562 state->constant_pool_address =
563 reinterpret_cast<Address*>(fp + ExitFrameConstants::kConstantPoolOffset);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100564}
565
566
Steve Blocka7e24c12009-10-30 11:49:00 +0000567Address StandardFrame::GetExpressionAddress(int n) const {
568 const int offset = StandardFrameConstants::kExpressionsOffset;
569 return fp() + offset - n * kPointerSize;
570}
571
572
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000573Object* StandardFrame::GetExpression(Address fp, int index) {
574 return Memory::Object_at(GetExpressionAddress(fp, index));
575}
576
577
578Address StandardFrame::GetExpressionAddress(Address fp, int n) {
579 const int offset = StandardFrameConstants::kExpressionsOffset;
580 return fp + offset - n * kPointerSize;
581}
582
583
Steve Blocka7e24c12009-10-30 11:49:00 +0000584int StandardFrame::ComputeExpressionsCount() const {
585 const int offset =
586 StandardFrameConstants::kExpressionsOffset + kPointerSize;
587 Address base = fp() + offset;
588 Address limit = sp();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000589 DCHECK(base >= limit); // stack grows downwards
Steve Blocka7e24c12009-10-30 11:49:00 +0000590 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000591 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000592}
593
594
595void StandardFrame::ComputeCallerState(State* state) const {
596 state->sp = caller_sp();
597 state->fp = caller_fp();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100598 state->pc_address = ResolveReturnAddressLocation(
599 reinterpret_cast<Address*>(ComputePCAddress(fp())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 state->constant_pool_address =
601 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000602}
603
604
Steve Block6ded16b2010-05-10 14:33:55 +0100605void StandardFrame::SetCallerFp(Address caller_fp) {
606 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
607 caller_fp;
608}
609
610
Steve Blocka7e24c12009-10-30 11:49:00 +0000611bool StandardFrame::IsExpressionInsideHandler(int n) const {
612 Address address = GetExpressionAddress(n);
613 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
614 if (it.handler()->includes(address)) return true;
615 }
616 return false;
617}
618
619
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100621 // Make sure that we're not doing "safe" stack frame iteration. We cannot
622 // possibly find pointers in optimized frames in that state.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623 DCHECK(can_access_heap_objects());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100624
625 // Compute the safepoint information.
626 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100627 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100628 Code* code = StackFrame::GetSafepointData(
Ben Murdoch8b112d22011-06-08 16:22:53 +0100629 isolate(), pc(), &safepoint_entry, &stack_slots);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100630 unsigned slot_space = stack_slots * kPointerSize;
631
Ben Murdoch8b112d22011-06-08 16:22:53 +0100632 // Visit the outgoing parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100633 Object** parameters_base = &Memory::Object_at(sp());
634 Object** parameters_limit = &Memory::Object_at(
635 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
636
Ben Murdochb8e0da22011-05-16 14:20:40 +0100637 // Visit the parameters that may be on top of the saved registers.
638 if (safepoint_entry.argument_count() > 0) {
639 v->VisitPointers(parameters_base,
640 parameters_base + safepoint_entry.argument_count());
641 parameters_base += safepoint_entry.argument_count();
642 }
643
644 // Skip saved double registers.
645 if (safepoint_entry.has_doubles()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000646 // Number of doubles not known at snapshot time.
647 DCHECK(!isolate()->serializer_enabled());
648 parameters_base += DoubleRegister::NumAllocatableRegisters() *
Ben Murdochb8e0da22011-05-16 14:20:40 +0100649 kDoubleSize / kPointerSize;
650 }
651
Ben Murdochb0fe1622011-05-05 13:52:32 +0100652 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100653 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100654 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100655 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100656 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
657 v->VisitPointer(parameters_base + reg_stack_index);
658 }
659 }
660 // Skip the words containing the register values.
661 parameters_base += kNumSafepointRegisters;
662 }
663
664 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100665 uint8_t* safepoint_bits = safepoint_entry.bits();
666 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100667
668 // Visit the rest of the parameters.
669 v->VisitPointers(parameters_base, parameters_limit);
670
671 // Visit pointer spill slots and locals.
672 for (unsigned index = 0; index < stack_slots; index++) {
673 int byte_index = index >> kBitsPerByteLog2;
674 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100675 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100676 v->VisitPointer(parameters_limit + index);
677 }
678 }
679
Ben Murdochb0fe1622011-05-05 13:52:32 +0100680 // Visit the return address in the callee and incoming arguments.
681 IteratePc(v, pc_address(), code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000682
683 // Visit the context in stub frame and JavaScript frame.
684 // Visit the function in JavaScript frame.
685 Object** fixed_base = &Memory::Object_at(
686 fp() + StandardFrameConstants::kMarkerOffset);
687 Object** fixed_limit = &Memory::Object_at(fp());
688 v->VisitPointers(fixed_base, fixed_limit);
689}
690
691
692void StubFrame::Iterate(ObjectVisitor* v) const {
693 IterateCompiledFrame(v);
694}
695
696
697Code* StubFrame::unchecked_code() const {
698 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
699}
700
701
702Address StubFrame::GetCallerStackPointer() const {
703 return fp() + ExitFrameConstants::kCallerSPDisplacement;
704}
705
706
707int StubFrame::GetNumberOfIncomingArguments() const {
708 return 0;
709}
710
711
712void OptimizedFrame::Iterate(ObjectVisitor* v) const {
713#ifdef DEBUG
714 // Make sure that optimized frames do not contain any stack handlers.
715 StackHandlerIterator it(this, top_handler());
716 DCHECK(it.done());
717#endif
718
719 IterateCompiledFrame(v);
720}
721
722
723void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
724 Memory::Object_at(GetParameterSlot(index)) = value;
Steve Blocka7e24c12009-10-30 11:49:00 +0000725}
726
727
728bool JavaScriptFrame::IsConstructor() const {
729 Address fp = caller_fp();
730 if (has_adapted_arguments()) {
731 // Skip the arguments adaptor frame and look at the real caller.
732 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
733 }
734 return IsConstructFrame(fp);
735}
736
737
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000738int JavaScriptFrame::GetArgumentsLength() const {
739 // If there is an arguments adaptor frame get the arguments length from it.
740 if (has_adapted_arguments()) {
741 return Smi::cast(GetExpression(caller_fp(), 0))->value();
742 } else {
743 return GetNumberOfIncomingArguments();
744 }
745}
746
747
Iain Merrick75681382010-08-19 15:07:18 +0100748Code* JavaScriptFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000749 return function()->code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000750}
751
752
Ben Murdoch8b112d22011-06-08 16:22:53 +0100753int JavaScriptFrame::GetNumberOfIncomingArguments() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000754 DCHECK(can_access_heap_objects() &&
Ben Murdoch8b112d22011-06-08 16:22:53 +0100755 isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
756
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000757 return function()->shared()->formal_parameter_count();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100758}
759
760
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100761Address JavaScriptFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100762 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100763}
764
765
Ben Murdochb0fe1622011-05-05 13:52:32 +0100766void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000767 DCHECK(functions->length() == 0);
768 functions->Add(function());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100769}
770
771
772void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000773 DCHECK(functions->length() == 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100774 Code* code_pointer = LookupCode();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100775 int offset = static_cast<int>(pc() - code_pointer->address());
776 FrameSummary summary(receiver(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000777 function(),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100778 code_pointer,
779 offset,
780 IsConstructor());
781 functions->Add(summary);
782}
783
784
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000785void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
786 Address pc, FILE* file,
787 bool print_line_number) {
788 PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
789 function->PrintName(file);
790 int code_offset = static_cast<int>(pc - code->instruction_start());
791 PrintF(file, "+%d", code_offset);
792 if (print_line_number) {
793 SharedFunctionInfo* shared = function->shared();
794 int source_pos = code->SourcePosition(pc);
795 Object* maybe_script = shared->script();
796 if (maybe_script->IsScript()) {
797 Script* script = Script::cast(maybe_script);
798 int line = script->GetLineNumber(source_pos) + 1;
799 Object* script_name_raw = script->name();
800 if (script_name_raw->IsString()) {
801 String* script_name = String::cast(script->name());
802 SmartArrayPointer<char> c_script_name =
803 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
804 PrintF(file, " at %s:%d", c_script_name.get(), line);
805 } else {
806 PrintF(file, " at <unknown>:%d", line);
807 }
808 } else {
809 PrintF(file, " at <unknown>:<unknown>");
810 }
811 }
812}
813
814
815void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100816 bool print_line_number) {
817 // constructor calls
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000818 DisallowHeapAllocation no_allocation;
819 JavaScriptFrameIterator it(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100820 while (!it.done()) {
821 if (it.frame()->is_java_script()) {
822 JavaScriptFrame* frame = it.frame();
823 if (frame->IsConstructor()) PrintF(file, "new ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000824 PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
825 frame->pc(), file, print_line_number);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100826 if (print_args) {
827 // function arguments
828 // (we are intentionally only printing the actually
829 // supplied parameters, not all parameters required)
830 PrintF(file, "(this=");
831 frame->receiver()->ShortPrint(file);
832 const int length = frame->ComputeParametersCount();
833 for (int i = 0; i < length; i++) {
834 PrintF(file, ", ");
835 frame->GetParameter(i)->ShortPrint(file);
836 }
837 PrintF(file, ")");
838 }
839 break;
840 }
841 it.Advance();
842 }
843}
844
845
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846void JavaScriptFrame::SaveOperandStack(FixedArray* store,
847 int* stack_handler_index) const {
848 int operands_count = store->length();
849 DCHECK_LE(operands_count, ComputeOperandsCount());
850
851 // Visit the stack in LIFO order, saving operands and stack handlers into the
852 // array. The saved stack handlers store a link to the next stack handler,
853 // which will allow RestoreOperandStack to rewind the handlers.
854 StackHandlerIterator it(this, top_handler());
855 int i = operands_count - 1;
856 *stack_handler_index = -1;
857 for (; !it.done(); it.Advance()) {
858 StackHandler* handler = it.handler();
859 // Save operands pushed after the handler was pushed.
860 for (; GetOperandSlot(i) < handler->address(); i--) {
861 store->set(i, GetOperand(i));
862 }
863 DCHECK_GE(i + 1, StackHandlerConstants::kSlotCount);
864 DCHECK_EQ(handler->address(), GetOperandSlot(i));
865 int next_stack_handler_index = i + 1 - StackHandlerConstants::kSlotCount;
866 handler->Unwind(isolate(), store, next_stack_handler_index,
867 *stack_handler_index);
868 *stack_handler_index = next_stack_handler_index;
869 i -= StackHandlerConstants::kSlotCount;
870 }
871
872 // Save any remaining operands.
873 for (; i >= 0; i--) {
874 store->set(i, GetOperand(i));
875 }
876}
877
878
879void JavaScriptFrame::RestoreOperandStack(FixedArray* store,
880 int stack_handler_index) {
881 int operands_count = store->length();
882 DCHECK_LE(operands_count, ComputeOperandsCount());
883 int i = 0;
884 while (i <= stack_handler_index) {
885 if (i < stack_handler_index) {
886 // An operand.
887 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
888 Memory::Object_at(GetOperandSlot(i)) = store->get(i);
889 i++;
890 } else {
891 // A stack handler.
892 DCHECK_EQ(i, stack_handler_index);
893 // The FixedArray store grows up. The stack grows down. So the operand
894 // slot for i actually points to the bottom of the top word in the
895 // handler. The base of the StackHandler* is the address of the bottom
896 // word, which will be the last slot that is in the handler.
897 int handler_slot_index = i + StackHandlerConstants::kSlotCount - 1;
898 StackHandler *handler =
899 StackHandler::FromAddress(GetOperandSlot(handler_slot_index));
900 stack_handler_index = handler->Rewind(isolate(), store, i, fp());
901 i += StackHandlerConstants::kSlotCount;
902 }
903 }
904
905 for (; i < operands_count; i++) {
906 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
907 Memory::Object_at(GetOperandSlot(i)) = store->get(i);
908 }
909}
910
911
Ben Murdochb0fe1622011-05-05 13:52:32 +0100912void FrameSummary::Print() {
913 PrintF("receiver: ");
914 receiver_->ShortPrint();
915 PrintF("\nfunction: ");
916 function_->shared()->DebugName()->ShortPrint();
917 PrintF("\ncode: ");
918 code_->ShortPrint();
919 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
920 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
921 PrintF("\npc: %d\n", offset_);
922}
923
924
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000925JSFunction* OptimizedFrame::LiteralAt(FixedArray* literal_array,
926 int literal_id) {
927 if (literal_id == Translation::kSelfLiteralId) {
928 return function();
929 }
930
931 return JSFunction::cast(literal_array->get(literal_id));
932}
933
934
Ben Murdochb0fe1622011-05-05 13:52:32 +0100935void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936 DCHECK(frames->length() == 0);
937 DCHECK(is_optimized());
938
939 // Delegate to JS frame in absence of turbofan deoptimization.
940 // TODO(turbofan): Revisit once we support deoptimization across the board.
941 if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
942 return JavaScriptFrame::Summarize(frames);
943 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100944
Steve Block1e0659c2011-05-24 12:43:12 +0100945 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100946 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947 FixedArray* literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100948
949 // BUG(3243555): Since we don't have a lazy-deopt registered at
950 // throw-statements, we can't use the translation at the call-site of
951 // throw. An entry with no deoptimization index indicates a call-site
952 // without a lazy-deopt. As a consequence we are not allowed to inline
953 // functions containing throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000954 DCHECK(deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100955
956 TranslationIterator it(data->TranslationByteArray(),
957 data->TranslationIndex(deopt_index)->value());
958 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000959 DCHECK(opcode == Translation::BEGIN);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100960 it.Next(); // Drop frame count.
961 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100962
963 // We create the summary in reverse order because the frames
964 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100965 bool is_constructor = IsConstructor();
966 int i = jsframe_count;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100967 while (i > 0) {
968 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100969 if (opcode == Translation::JS_FRAME) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100970 i--;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000971 BailoutId ast_id = BailoutId(it.Next());
972 JSFunction* function = LiteralAt(literal_array, it.Next());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100973 it.Next(); // Skip height.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100974
975 // The translation commands are ordered and the receiver is always
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000976 // at the first position.
977 // If we are at a call, the receiver is always in a stack slot.
978 // Otherwise we are not guaranteed to get the receiver value.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100979 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch257744e2011-11-30 15:57:28 +0000980 int index = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100981
982 // Get the correct receiver in the optimized frame.
983 Object* receiver = NULL;
Ben Murdoch257744e2011-11-30 15:57:28 +0000984 if (opcode == Translation::LITERAL) {
985 receiver = data->LiteralArray()->get(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000986 } else if (opcode == Translation::STACK_SLOT) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000987 // Positive index means the value is spilled to the locals
988 // area. Negative means it is stored in the incoming parameter
989 // area.
990 if (index >= 0) {
991 receiver = GetExpression(index);
992 } else {
993 // Index -1 overlaps with last parameter, -n with the first parameter,
994 // (-n - 1) with the receiver with n being the number of parameters
995 // of the outermost, optimized frame.
996 int parameter_count = ComputeParametersCount();
997 int parameter_index = index + parameter_count;
998 receiver = (parameter_index == -1)
999 ? this->receiver()
1000 : this->GetParameter(parameter_index);
1001 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002 } else {
1003 // The receiver is not in a stack slot nor in a literal. We give up.
1004 // TODO(3029): Materializing a captured object (or duplicated
1005 // object) is hard, we return undefined for now. This breaks the
1006 // produced stack trace, as constructor frames aren't marked as
1007 // such anymore.
1008 receiver = isolate()->heap()->undefined_value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001009 }
1010
1011 Code* code = function->shared()->code();
1012 DeoptimizationOutputData* output_data =
1013 DeoptimizationOutputData::cast(code->deoptimization_data());
1014 unsigned entry = Deoptimizer::GetOutputInfo(output_data,
1015 ast_id,
1016 function->shared());
1017 unsigned pc_offset =
1018 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001019 DCHECK(pc_offset > 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001020
1021 FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
1022 frames->Add(summary);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001023 is_constructor = false;
1024 } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) {
1025 // The next encountered JS_FRAME will be marked as a constructor call.
1026 it.Skip(Translation::NumberOfOperandsFor(opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001027 DCHECK(!is_constructor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001028 is_constructor = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001029 } else {
1030 // Skip over operands to advance to the next opcode.
1031 it.Skip(Translation::NumberOfOperandsFor(opcode));
1032 }
1033 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034 DCHECK(!is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001035}
1036
1037
1038DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
1039 int* deopt_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001040 DCHECK(is_optimized());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001041
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042 JSFunction* opt_function = function();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001043 Code* code = opt_function->code();
1044
1045 // The code object may have been replaced by lazy deoptimization. Fall
1046 // back to a slow search in this case to find the original optimized
1047 // code object.
1048 if (!code->contains(pc())) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001049 code = isolate()->inner_pointer_to_code_cache()->
1050 GcSafeFindCodeForInnerPointer(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001051 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001052 DCHECK(code != NULL);
1053 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001054
Ben Murdochb8e0da22011-05-16 14:20:40 +01001055 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1056 *deopt_index = safepoint_entry.deoptimization_index();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001057 DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001058
1059 return DeoptimizationInputData::cast(code->deoptimization_data());
1060}
1061
1062
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001063int OptimizedFrame::GetInlineCount() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001064 DCHECK(is_optimized());
1065
1066 // Delegate to JS frame in absence of turbofan deoptimization.
1067 // TODO(turbofan): Revisit once we support deoptimization across the board.
1068 if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
1069 return JavaScriptFrame::GetInlineCount();
1070 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001071
1072 int deopt_index = Safepoint::kNoDeoptimizationIndex;
1073 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
1074
1075 TranslationIterator it(data->TranslationByteArray(),
1076 data->TranslationIndex(deopt_index)->value());
1077 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001078 DCHECK(opcode == Translation::BEGIN);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001079 USE(opcode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001080 it.Next(); // Drop frame count.
1081 int jsframe_count = it.Next();
1082 return jsframe_count;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001083}
1084
1085
Ben Murdochb0fe1622011-05-05 13:52:32 +01001086void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087 DCHECK(functions->length() == 0);
1088 DCHECK(is_optimized());
1089
1090 // Delegate to JS frame in absence of turbofan deoptimization.
1091 // TODO(turbofan): Revisit once we support deoptimization across the board.
1092 if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
1093 return JavaScriptFrame::GetFunctions(functions);
1094 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001095
Steve Block1e0659c2011-05-24 12:43:12 +01001096 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001097 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001098 FixedArray* literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001099
1100 TranslationIterator it(data->TranslationByteArray(),
1101 data->TranslationIndex(deopt_index)->value());
1102 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001103 DCHECK(opcode == Translation::BEGIN);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001104 it.Next(); // Drop frame count.
1105 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001106
1107 // We insert the frames in reverse order because the frames
1108 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001109 while (jsframe_count > 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001110 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001111 if (opcode == Translation::JS_FRAME) {
1112 jsframe_count--;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001113 it.Next(); // Skip ast id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001114 JSFunction* function = LiteralAt(literal_array, it.Next());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001115 it.Next(); // Skip height.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001116 functions->Add(function);
1117 } else {
1118 // Skip over operands to advance to the next opcode.
1119 it.Skip(Translation::NumberOfOperandsFor(opcode));
1120 }
1121 }
1122}
1123
1124
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001125int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
1126 return Smi::cast(GetExpression(0))->value();
1127}
1128
1129
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001130Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001131 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001132}
1133
1134
1135Address InternalFrame::GetCallerStackPointer() const {
1136 // Internal frames have no arguments. The stack pointer of the
1137 // caller is at a fixed offset from the frame pointer.
1138 return fp() + StandardFrameConstants::kCallerSPOffset;
1139}
1140
1141
Iain Merrick75681382010-08-19 15:07:18 +01001142Code* ArgumentsAdaptorFrame::unchecked_code() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001143 return isolate()->builtins()->builtin(
Steve Block44f0eee2011-05-26 01:26:41 +01001144 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +00001145}
1146
1147
Iain Merrick75681382010-08-19 15:07:18 +01001148Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001149 const int offset = InternalFrameConstants::kCodeOffset;
1150 Object* code = Memory::Object_at(fp() + offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001151 DCHECK(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +01001152 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001153}
1154
1155
1156void StackFrame::PrintIndex(StringStream* accumulator,
1157 PrintMode mode,
1158 int index) {
1159 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1160}
1161
1162
1163void JavaScriptFrame::Print(StringStream* accumulator,
1164 PrintMode mode,
1165 int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001166 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001167 Object* receiver = this->receiver();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168 JSFunction* function = this->function();
Steve Blocka7e24c12009-10-30 11:49:00 +00001169
1170 accumulator->PrintSecurityTokenIfChanged(function);
1171 PrintIndex(accumulator, mode, index);
1172 Code* code = NULL;
1173 if (IsConstructor()) accumulator->Add("new ");
1174 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +01001175
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001176 // Get scope information for nicer output, if possible. If code is NULL, or
1177 // doesn't contain scope info, scope_info will return 0 for the number of
1178 // parameters, stack local variables, context local variables, stack slots,
1179 // or context slots.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180 SharedFunctionInfo* shared = function->shared();
1181 ScopeInfo* scope_info = shared->scope_info();
1182 Object* script_obj = shared->script();
1183 if (script_obj->IsScript()) {
1184 Script* script = Script::cast(script_obj);
1185 accumulator->Add(" [");
1186 accumulator->PrintName(script->name());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001187
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001188 Address pc = this->pc();
1189 if (code != NULL && code->kind() == Code::FUNCTION &&
1190 pc >= code->instruction_start() && pc < code->instruction_end()) {
1191 int source_pos = code->SourcePosition(pc);
1192 int line = script->GetLineNumber(source_pos) + 1;
1193 accumulator->Add(":%d", line);
1194 } else {
1195 int function_start_pos = shared->start_position();
1196 int line = script->GetLineNumber(function_start_pos) + 1;
1197 accumulator->Add(":~%d", line);
Steve Block6ded16b2010-05-10 14:33:55 +01001198 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001199
1200 accumulator->Add("] ");
Steve Block6ded16b2010-05-10 14:33:55 +01001201 }
1202
Steve Blocka7e24c12009-10-30 11:49:00 +00001203 accumulator->Add("(this=%o", receiver);
1204
Steve Blocka7e24c12009-10-30 11:49:00 +00001205 // Print the parameters.
1206 int parameters_count = ComputeParametersCount();
1207 for (int i = 0; i < parameters_count; i++) {
1208 accumulator->Add(",");
1209 // If we have a name for the parameter we print it. Nameless
1210 // parameters are either because we have more actual parameters
1211 // than formal parameters or because we have no scope information.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001212 if (i < scope_info->ParameterCount()) {
1213 accumulator->PrintName(scope_info->ParameterName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001214 accumulator->Add("=");
1215 }
1216 accumulator->Add("%o", GetParameter(i));
1217 }
1218
1219 accumulator->Add(")");
1220 if (mode == OVERVIEW) {
1221 accumulator->Add("\n");
1222 return;
1223 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001224 if (is_optimized()) {
1225 accumulator->Add(" {\n// optimized frame\n}\n");
1226 return;
1227 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001228 accumulator->Add(" {\n");
1229
1230 // Compute the number of locals and expression stack elements.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001231 int stack_locals_count = scope_info->StackLocalCount();
1232 int heap_locals_count = scope_info->ContextLocalCount();
Steve Blocka7e24c12009-10-30 11:49:00 +00001233 int expressions_count = ComputeExpressionsCount();
1234
1235 // Print stack-allocated local variables.
1236 if (stack_locals_count > 0) {
1237 accumulator->Add(" // stack-allocated locals\n");
1238 }
1239 for (int i = 0; i < stack_locals_count; i++) {
1240 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001241 accumulator->PrintName(scope_info->StackLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001242 accumulator->Add(" = ");
1243 if (i < expressions_count) {
1244 accumulator->Add("%o", GetExpression(i));
1245 } else {
1246 accumulator->Add("// no expression found - inconsistent frame?");
1247 }
1248 accumulator->Add("\n");
1249 }
1250
1251 // Try to get hold of the context of this frame.
1252 Context* context = NULL;
1253 if (this->context() != NULL && this->context()->IsContext()) {
1254 context = Context::cast(this->context());
1255 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001256 while (context->IsWithContext()) {
1257 context = context->previous();
1258 DCHECK(context != NULL);
1259 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001260
1261 // Print heap-allocated local variables.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001262 if (heap_locals_count > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001263 accumulator->Add(" // heap-allocated locals\n");
1264 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001265 for (int i = 0; i < heap_locals_count; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001266 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001267 accumulator->PrintName(scope_info->ContextLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001268 accumulator->Add(" = ");
1269 if (context != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001270 int index = Context::MIN_CONTEXT_SLOTS + i;
1271 if (index < context->length()) {
1272 accumulator->Add("%o", context->get(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00001273 } else {
1274 accumulator->Add(
1275 "// warning: missing context slot - inconsistent frame?");
1276 }
1277 } else {
1278 accumulator->Add("// warning: no context found - inconsistent frame?");
1279 }
1280 accumulator->Add("\n");
1281 }
1282
1283 // Print the expression stack.
1284 int expressions_start = stack_locals_count;
1285 if (expressions_start < expressions_count) {
1286 accumulator->Add(" // expression stack (top to bottom)\n");
1287 }
1288 for (int i = expressions_count - 1; i >= expressions_start; i--) {
1289 if (IsExpressionInsideHandler(i)) continue;
1290 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1291 }
1292
1293 // Print details about the function.
1294 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001295 std::ostringstream os;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001296 SharedFunctionInfo* shared = function->shared();
1297 os << "--------- s o u r c e c o d e ---------\n"
1298 << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1299 << "\n-----------------------------------------\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001300 accumulator->Add(os.str().c_str());
Steve Blocka7e24c12009-10-30 11:49:00 +00001301 }
1302
1303 accumulator->Add("}\n\n");
1304}
1305
1306
1307void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1308 PrintMode mode,
1309 int index) const {
1310 int actual = ComputeParametersCount();
1311 int expected = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001312 JSFunction* function = this->function();
1313 expected = function->shared()->formal_parameter_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00001314
1315 PrintIndex(accumulator, mode, index);
1316 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1317 if (mode == OVERVIEW) {
1318 accumulator->Add("\n");
1319 return;
1320 }
1321 accumulator->Add(" {\n");
1322
1323 // Print actual arguments.
1324 if (actual > 0) accumulator->Add(" // actual arguments\n");
1325 for (int i = 0; i < actual; i++) {
1326 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1327 if (expected != -1 && i >= expected) {
1328 accumulator->Add(" // not passed to callee");
1329 }
1330 accumulator->Add("\n");
1331 }
1332
1333 accumulator->Add("}\n\n");
1334}
1335
1336
1337void EntryFrame::Iterate(ObjectVisitor* v) const {
1338 StackHandlerIterator it(this, top_handler());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001339 DCHECK(!it.done());
Steve Blocka7e24c12009-10-30 11:49:00 +00001340 StackHandler* handler = it.handler();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341 DCHECK(handler->is_js_entry());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001342 handler->Iterate(v, LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001343#ifdef DEBUG
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001344 // Make sure that the entry frame does not contain more than one
1345 // stack handler.
Steve Blocka7e24c12009-10-30 11:49:00 +00001346 it.Advance();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001347 DCHECK(it.done());
Steve Blocka7e24c12009-10-30 11:49:00 +00001348#endif
Ben Murdoch8b112d22011-06-08 16:22:53 +01001349 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001350}
1351
1352
1353void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001354 const int offset = StandardFrameConstants::kLastObjectOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +00001355 Object** base = &Memory::Object_at(sp());
1356 Object** limit = &Memory::Object_at(fp() + offset) + 1;
1357 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1358 StackHandler* handler = it.handler();
1359 // Traverse pointers down to - but not including - the next
1360 // handler in the handler chain. Update the base to skip the
1361 // handler and allow the handler to traverse its own pointers.
1362 const Address address = handler->address();
1363 v->VisitPointers(base, reinterpret_cast<Object**>(address));
1364 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1365 // Traverse the pointers in the handler itself.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001366 handler->Iterate(v, LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001367 }
1368 v->VisitPointers(base, limit);
1369}
1370
1371
1372void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1373 IterateExpressions(v);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001374 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001375}
1376
1377
1378void InternalFrame::Iterate(ObjectVisitor* v) const {
1379 // Internal frames only have object pointers on the expression stack
1380 // as they never have any arguments.
1381 IterateExpressions(v);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001382 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001383}
1384
1385
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001386void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
1387 Object** base = &Memory::Object_at(sp());
1388 Object** limit = &Memory::Object_at(fp() +
1389 kFirstRegisterParameterFrameOffset);
1390 v->VisitPointers(base, limit);
1391 base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset);
1392 const int offset = StandardFrameConstants::kLastObjectOffset;
1393 limit = &Memory::Object_at(fp() + offset) + 1;
1394 v->VisitPointers(base, limit);
1395 IteratePc(v, pc_address(), LookupCode());
1396}
1397
1398
1399Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
1400 return fp() + StandardFrameConstants::kCallerSPOffset;
1401}
1402
1403
1404Code* StubFailureTrampolineFrame::unchecked_code() const {
1405 Code* trampoline;
1406 StubFailureTrampolineStub(isolate(), NOT_JS_FUNCTION_STUB_MODE).
1407 FindCodeInCache(&trampoline);
1408 if (trampoline->contains(pc())) {
1409 return trampoline;
1410 }
1411
1412 StubFailureTrampolineStub(isolate(), JS_FUNCTION_STUB_MODE).
1413 FindCodeInCache(&trampoline);
1414 if (trampoline->contains(pc())) {
1415 return trampoline;
1416 }
1417
1418 UNREACHABLE();
1419 return NULL;
1420}
1421
1422
Steve Blocka7e24c12009-10-30 11:49:00 +00001423// -------------------------------------------------------------------------
1424
1425
1426JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001427 DCHECK(n >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001428 for (int i = 0; i <= n; i++) {
1429 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1430 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1431 iterator_.Advance();
1432 }
1433 UNREACHABLE();
1434 return NULL;
1435}
1436
1437
1438// -------------------------------------------------------------------------
1439
1440
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001441static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1442 MapWord map_word = object->map_word();
1443 return map_word.IsForwardingAddress() ?
1444 map_word.ToForwardingAddress()->map() : map_word.ToMap();
1445}
1446
1447
1448static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1449 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1450}
1451
1452
1453#ifdef DEBUG
1454static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1455 Map* map = GcSafeMapOfCodeSpaceObject(code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001456 DCHECK(map == code->GetHeap()->code_map());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001457 Address start = code->address();
1458 Address end = code->address() + code->SizeFromMap(map);
1459 return start <= addr && addr < end;
1460}
1461#endif
1462
1463
1464Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1465 Address inner_pointer) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001466 Code* code = reinterpret_cast<Code*>(object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001467 DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001468 return code;
1469}
1470
1471
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001472Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1473 Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001474 Heap* heap = isolate_->heap();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001475 // Check if the inner pointer points into a large object chunk.
1476 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1477 if (large_page != NULL) {
1478 return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1479 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001480
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001481 // Iterate through the page until we reach the end or find an object starting
1482 // after the inner pointer.
1483 Page* page = Page::FromAddress(inner_pointer);
1484
1485 Address addr = page->skip_list()->StartFor(inner_pointer);
1486
1487 Address top = heap->code_space()->top();
1488 Address limit = heap->code_space()->limit();
1489
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001490 while (true) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001491 if (addr == top && addr != limit) {
1492 addr = limit;
1493 continue;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001494 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001495
1496 HeapObject* obj = HeapObject::FromAddress(addr);
1497 int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1498 Address next_addr = addr + obj_size;
1499 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1500 addr = next_addr;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001501 }
1502}
1503
Ben Murdochb0fe1622011-05-05 13:52:32 +01001504
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001505InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1506 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001507 isolate_->counters()->pc_to_code()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001508 DCHECK(base::bits::IsPowerOfTwo32(kInnerPointerToCodeCacheSize));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001509 uint32_t hash = ComputeIntegerHash(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001510 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)),
Ben Murdochc7cc0282012-03-05 14:35:55 +00001511 v8::internal::kZeroHashSeed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001512 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1513 InnerPointerToCodeCacheEntry* entry = cache(index);
1514 if (entry->inner_pointer == inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001515 isolate_->counters()->pc_to_code_cached()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001516 DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001517 } else {
1518 // Because this code may be interrupted by a profiling signal that
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001519 // also queries the cache, we cannot update inner_pointer before the code
1520 // has been set. Otherwise, we risk trying to use a cache entry before
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001521 // the code has been computed.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001522 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001523 entry->safepoint_entry.Reset();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001524 entry->inner_pointer = inner_pointer;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001525 }
1526 return entry;
1527}
1528
1529
1530// -------------------------------------------------------------------------
1531
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001532
1533void StackHandler::Unwind(Isolate* isolate,
1534 FixedArray* array,
1535 int offset,
1536 int previous_handler_offset) const {
1537 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5);
1538 DCHECK_LE(0, offset);
1539 DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount);
1540 // Unwinding a stack handler into an array chains it in the opposite
1541 // direction, re-using the "next" slot as a "previous" link, so that stack
1542 // handlers can be later re-wound in the correct order. Decode the "state"
1543 // slot into "index" and "kind" and store them separately, using the fp slot.
1544 array->set(offset, Smi::FromInt(previous_handler_offset)); // next
1545 array->set(offset + 1, *code_address()); // code
1546 array->set(offset + 2, Smi::FromInt(static_cast<int>(index()))); // state
1547 array->set(offset + 3, *context_address()); // context
1548 array->set(offset + 4, Smi::FromInt(static_cast<int>(kind()))); // fp
1549
1550 *isolate->handler_address() = next()->address();
Steve Blocka7e24c12009-10-30 11:49:00 +00001551}
1552
1553
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001554int StackHandler::Rewind(Isolate* isolate,
1555 FixedArray* array,
1556 int offset,
1557 Address fp) {
1558 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5);
1559 DCHECK_LE(0, offset);
1560 DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount);
1561 Smi* prev_handler_offset = Smi::cast(array->get(offset));
1562 Code* code = Code::cast(array->get(offset + 1));
1563 Smi* smi_index = Smi::cast(array->get(offset + 2));
1564 Object* context = array->get(offset + 3);
1565 Smi* smi_kind = Smi::cast(array->get(offset + 4));
Steve Blocka7e24c12009-10-30 11:49:00 +00001566
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001567 unsigned state = KindField::encode(static_cast<Kind>(smi_kind->value())) |
1568 IndexField::encode(static_cast<unsigned>(smi_index->value()));
1569
1570 Memory::Address_at(address() + StackHandlerConstants::kNextOffset) =
1571 *isolate->handler_address();
1572 Memory::Object_at(address() + StackHandlerConstants::kCodeOffset) = code;
1573 Memory::uintptr_at(address() + StackHandlerConstants::kStateOffset) = state;
1574 Memory::Object_at(address() + StackHandlerConstants::kContextOffset) =
1575 context;
1576 SetFp(address() + StackHandlerConstants::kFPOffset, fp);
1577
1578 *isolate->handler_address() = address();
1579
1580 return prev_handler_offset->value();
1581}
1582
1583
1584// -------------------------------------------------------------------------
1585
1586int NumRegs(RegList reglist) { return base::bits::CountPopulation32(reglist); }
1587
1588
1589struct JSCallerSavedCodeData {
Steve Block44f0eee2011-05-26 01:26:41 +01001590 int reg_code[kNumJSCallerSaved];
1591};
1592
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001593JSCallerSavedCodeData caller_saved_code_data;
Steve Block44f0eee2011-05-26 01:26:41 +01001594
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001595void SetUpJSCallerSavedCodeData() {
1596 int i = 0;
1597 for (int r = 0; r < kNumRegs; r++)
1598 if ((kJSCallerSaved & (1 << r)) != 0)
1599 caller_saved_code_data.reg_code[i++] = r;
1600
1601 DCHECK(i == kNumJSCallerSaved);
1602}
1603
Steve Block44f0eee2011-05-26 01:26:41 +01001604
1605int JSCallerSavedCode(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001606 DCHECK(0 <= n && n < kNumJSCallerSaved);
1607 return caller_saved_code_data.reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001608}
1609
1610
Steve Block6ded16b2010-05-10 14:33:55 +01001611#define DEFINE_WRAPPER(type, field) \
1612class field##_Wrapper : public ZoneObject { \
1613 public: /* NOLINT */ \
1614 field##_Wrapper(const field& original) : frame_(original) { \
1615 } \
1616 field frame_; \
1617};
1618STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1619#undef DEFINE_WRAPPER
1620
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001621static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
Steve Block6ded16b2010-05-10 14:33:55 +01001622#define FRAME_TYPE_CASE(type, field) \
1623 case StackFrame::type: { \
1624 field##_Wrapper* wrapper = \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001625 new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
Steve Block6ded16b2010-05-10 14:33:55 +01001626 return &wrapper->frame_; \
1627 }
1628
1629 switch (frame->type()) {
1630 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1631 default: UNREACHABLE();
1632 }
1633#undef FRAME_TYPE_CASE
1634 return NULL;
1635}
1636
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001637
1638Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
1639 ZoneList<StackFrame*> list(10, zone);
1640 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1641 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1642 list.Add(frame, zone);
Steve Block6ded16b2010-05-10 14:33:55 +01001643 }
1644 return list.ToVector();
1645}
1646
1647
Steve Blocka7e24c12009-10-30 11:49:00 +00001648} } // namespace v8::internal