blob: d60ab29c4e62c2e60cc52a7b1cf54378076ed8e3 [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 Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/ast/ast.h"
10#include "src/ast/scopeinfo.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/base/bits.h"
12#include "src/deoptimizer.h"
13#include "src/frames-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/full-codegen/full-codegen.h"
15#include "src/register-configuration.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016#include "src/safepoint-table.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017#include "src/string-stream.h"
18#include "src/vm-state-inl.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000019
Steve Blocka7e24c12009-10-30 11:49:00 +000020namespace v8 {
21namespace internal {
22
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023ReturnAddressLocationResolver
24 StackFrame::return_address_location_resolver_ = NULL;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010025
26
Steve Blocka7e24c12009-10-30 11:49:00 +000027// Iterator that supports traversing the stack handlers of a
28// particular frame. Needs to know the top of the handler chain.
29class StackHandlerIterator BASE_EMBEDDED {
30 public:
31 StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
32 : limit_(frame->fp()), handler_(handler) {
33 // Make sure the handler has already been unwound to this frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034 DCHECK(frame->sp() <= handler->address());
Steve Blocka7e24c12009-10-30 11:49:00 +000035 }
36
37 StackHandler* handler() const { return handler_; }
38
39 bool done() {
40 return handler_ == NULL || handler_->address() > limit_;
41 }
42 void Advance() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +000044 handler_ = handler_->next();
45 }
46
47 private:
48 const Address limit_;
49 StackHandler* handler_;
50};
51
52
53// -------------------------------------------------------------------------
54
55
56#define INITIALIZE_SINGLETON(type, field) field##_(this),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
58 bool can_access_heap_objects)
Ben Murdoch8b112d22011-06-08 16:22:53 +010059 : isolate_(isolate),
60 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
61 frame_(NULL), handler_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 can_access_heap_objects_(can_access_heap_objects) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010063}
Steve Blocka7e24c12009-10-30 11:49:00 +000064#undef INITIALIZE_SINGLETON
65
66
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067StackFrameIterator::StackFrameIterator(Isolate* isolate)
68 : StackFrameIteratorBase(isolate, true) {
69 Reset(isolate->thread_local_top());
70}
71
72
73StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
74 : StackFrameIteratorBase(isolate, true) {
75 Reset(t);
76}
77
78
79void StackFrameIterator::Advance() {
80 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +000081 // Compute the state of the calling frame before restoring
82 // callee-saved registers and unwinding handlers. This allows the
83 // frame code that computes the caller state to access the top
84 // handler and the value of any callee-saved register if needed.
85 StackFrame::State state;
86 StackFrame::Type type = frame_->GetCallerState(&state);
87
88 // Unwind handlers corresponding to the current frame.
89 StackHandlerIterator it(frame_, handler_);
90 while (!it.done()) it.Advance();
91 handler_ = it.handler();
92
93 // Advance to the calling frame.
94 frame_ = SingletonFor(type, &state);
95
96 // When we're done iterating over the stack frames, the handler
97 // chain must have been completely unwound.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 DCHECK(!done() || handler_ == NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +000099}
100
101
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102void StackFrameIterator::Reset(ThreadLocalTop* top) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 StackFrame::State state;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 StackFrame::Type type = ExitFrame::GetStateForFramePointer(
105 Isolate::c_entry_fp(top), &state);
106 handler_ = StackHandler::FromAddress(Isolate::handler(top));
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100107 if (SingletonFor(type) == NULL) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 frame_ = SingletonFor(type, &state);
109}
110
111
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
Steve Blocka7e24c12009-10-30 11:49:00 +0000113 StackFrame::State* state) {
114 if (type == StackFrame::NONE) return NULL;
115 StackFrame* result = SingletonFor(type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116 DCHECK(result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000117 result->state_ = *state;
118 return result;
119}
120
121
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000123#define FRAME_TYPE_CASE(type, field) \
124 case StackFrame::type: result = &field##_; break;
125
126 StackFrame* result = NULL;
127 switch (type) {
128 case StackFrame::NONE: return NULL;
129 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
130 default: break;
131 }
132 return result;
133
134#undef FRAME_TYPE_CASE
135}
136
137
138// -------------------------------------------------------------------------
139
140
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141JavaScriptFrameIterator::JavaScriptFrameIterator(
142 Isolate* isolate, StackFrame::Id id)
143 : iterator_(isolate) {
144 while (!done()) {
145 Advance();
146 if (frame()->id() == id) return;
147 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000148}
149
150
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151void JavaScriptFrameIterator::Advance() {
152 do {
153 iterator_.Advance();
154 } while (!iterator_.done() && !iterator_.frame()->is_java_script());
155}
156
157
158void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
159 if (!frame()->has_adapted_arguments()) return;
160 iterator_.Advance();
161 DCHECK(iterator_.frame()->is_arguments_adaptor());
162}
163
164
165// -------------------------------------------------------------------------
166
167
Ben Murdoch8b112d22011-06-08 16:22:53 +0100168StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
169 : JavaScriptFrameIterator(isolate) {
170 if (!done() && !IsValidFrame()) Advance();
171}
172
173
Steve Blocka7e24c12009-10-30 11:49:00 +0000174void StackTraceFrameIterator::Advance() {
175 while (true) {
176 JavaScriptFrameIterator::Advance();
177 if (done()) return;
Leon Clarke4515c472010-02-03 11:58:03 +0000178 if (IsValidFrame()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000179 }
180}
181
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000182
Leon Clarke4515c472010-02-03 11:58:03 +0000183bool StackTraceFrameIterator::IsValidFrame() {
184 if (!frame()->function()->IsJSFunction()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 Object* script = frame()->function()->shared()->script();
Leon Clarke4515c472010-02-03 11:58:03 +0000186 // Don't show functions from native scripts to user.
187 return (script->IsScript() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 Script::TYPE_NATIVE != Script::cast(script)->type());
Leon Clarke4515c472010-02-03 11:58:03 +0000189}
190
Steve Blocka7e24c12009-10-30 11:49:00 +0000191
192// -------------------------------------------------------------------------
193
194
195SafeStackFrameIterator::SafeStackFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100196 Isolate* isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197 Address fp, Address sp, Address js_entry_sp)
198 : StackFrameIteratorBase(isolate, false),
199 low_bound_(sp),
200 high_bound_(js_entry_sp),
201 top_frame_type_(StackFrame::NONE),
202 external_callback_scope_(isolate->external_callback_scope()) {
203 StackFrame::State state;
204 StackFrame::Type type;
Steve Block44f0eee2011-05-26 01:26:41 +0100205 ThreadLocalTop* top = isolate->thread_local_top();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206 if (IsValidTop(top)) {
207 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
208 top_frame_type_ = type;
209 } else if (IsValidStackAddress(fp)) {
210 DCHECK(fp != NULL);
211 state.fp = fp;
212 state.sp = sp;
213 state.pc_address = StackFrame::ResolveReturnAddressLocation(
214 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
215 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
216 // we check only that kMarkerOffset is within the stack bounds and do
217 // compile time check that kContextOffset slot is pushed on the stack before
218 // kMarkerOffset.
219 STATIC_ASSERT(StandardFrameConstants::kMarkerOffset <
220 StandardFrameConstants::kContextOffset);
221 Address frame_marker = fp + StandardFrameConstants::kMarkerOffset;
222 if (IsValidStackAddress(frame_marker)) {
223 type = StackFrame::ComputeType(this, &state);
224 top_frame_type_ = type;
225 } else {
226 // Mark the frame as JAVA_SCRIPT if we cannot determine its type.
227 // The frame anyways will be skipped.
228 type = StackFrame::JAVA_SCRIPT;
229 // Top frame is incomplete so we cannot reliably determine its type.
230 top_frame_type_ = StackFrame::NONE;
231 }
232 } else {
233 return;
234 }
235 if (SingletonFor(type) == NULL) return;
236 frame_ = SingletonFor(type, &state);
237 if (frame_ == NULL) return;
238
239 Advance();
240
241 if (frame_ != NULL && !frame_->is_exit() &&
242 external_callback_scope_ != NULL &&
243 external_callback_scope_->scope_address() < frame_->fp()) {
244 // Skip top ExternalCallbackScope if we already advanced to a JS frame
245 // under it. Sampler will anyways take this top external callback.
246 external_callback_scope_ = external_callback_scope_->previous();
247 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100248}
249
250
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
252 Address c_entry_fp = Isolate::c_entry_fp(top);
253 if (!IsValidExitFrame(c_entry_fp)) return false;
254 // There should be at least one JS_ENTRY stack handler.
255 Address handler = Isolate::handler(top);
256 if (handler == NULL) return false;
257 // Check that there are no js frames on top of the native frames.
258 return c_entry_fp < handler;
259}
260
261
262void SafeStackFrameIterator::AdvanceOneFrame() {
263 DCHECK(!done());
264 StackFrame* last_frame = frame_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000265 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266 // Before advancing to the next stack frame, perform pointer validity tests.
267 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
268 frame_ = NULL;
269 return;
270 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000271
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 // Advance to the previous frame.
273 StackFrame::State state;
274 StackFrame::Type type = frame_->GetCallerState(&state);
275 frame_ = SingletonFor(type, &state);
276 if (frame_ == NULL) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000277
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 // Check that we have actually moved to the previous frame in the stack.
279 if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
280 frame_ = NULL;
281 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000282}
283
284
285bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
286 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
287}
288
289
290bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
291 StackFrame::State state;
292 if (frame->is_entry() || frame->is_entry_construct()) {
293 // See EntryFrame::GetCallerState. It computes the caller FP address
294 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
295 // sure that caller FP address is valid.
296 Address caller_fp = Memory::Address_at(
297 frame->fp() + EntryFrameConstants::kCallerFPOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 if (!IsValidExitFrame(caller_fp)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000299 } else if (frame->is_arguments_adaptor()) {
300 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
301 // the number of arguments is stored on stack as Smi. We need to check
302 // that it really an Smi.
303 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
304 GetExpression(0);
305 if (!number_of_args->IsSmi()) {
306 return false;
307 }
308 }
309 frame->ComputeCallerState(&state);
310 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311 SingletonFor(frame->GetCallerState(&state)) != NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000312}
313
314
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
316 if (!IsValidStackAddress(fp)) return false;
317 Address sp = ExitFrame::ComputeStackPointer(fp);
318 if (!IsValidStackAddress(sp)) return false;
319 StackFrame::State state;
320 ExitFrame::FillState(fp, sp, &state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 return *state.pc_address != NULL;
322}
323
324
325void SafeStackFrameIterator::Advance() {
326 while (true) {
327 AdvanceOneFrame();
328 if (done()) return;
329 if (frame_->is_java_script()) return;
330 if (frame_->is_exit() && external_callback_scope_) {
331 // Some of the EXIT frames may have ExternalCallbackScope allocated on
332 // top of them. In that case the scope corresponds to the first EXIT
333 // frame beneath it. There may be other EXIT frames on top of the
334 // ExternalCallbackScope, just skip them as we cannot collect any useful
335 // information about them.
336 if (external_callback_scope_->scope_address() < frame_->fp()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337 frame_->state_.pc_address =
338 external_callback_scope_->callback_entrypoint_address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339 external_callback_scope_ = external_callback_scope_->previous();
340 DCHECK(external_callback_scope_ == NULL ||
341 external_callback_scope_->scope_address() > frame_->fp());
342 return;
343 }
344 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000345 }
346}
347
348
349// -------------------------------------------------------------------------
350
351
Ben Murdoch8b112d22011-06-08 16:22:53 +0100352Code* StackFrame::GetSafepointData(Isolate* isolate,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100353 Address inner_pointer,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100354 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100355 unsigned* stack_slots) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100356 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
357 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100358 if (!entry->safepoint_entry.is_valid()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100359 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360 DCHECK(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100361 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 DCHECK(entry->safepoint_entry.Equals(
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100363 entry->code->GetSafepointEntry(inner_pointer)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100364 }
365
366 // Fill in the results and return the code.
367 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100368 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100369 *stack_slots = code->stack_slots();
370 return code;
371}
372
373
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100374#ifdef DEBUG
375static bool GcSafeCodeContains(HeapObject* object, Address addr);
376#endif
377
378
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000379void StackFrame::IteratePc(ObjectVisitor* v, Address* pc_address,
380 Address* constant_pool_address, Code* holder) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100381 Address pc = *pc_address;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000382 DCHECK(GcSafeCodeContains(holder, pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100383 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
384 Object* code = holder;
385 v->VisitPointer(&code);
386 if (code != holder) {
387 holder = reinterpret_cast<Code*>(code);
388 pc = holder->instruction_start() + pc_offset;
389 *pc_address = pc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000390 if (FLAG_enable_embedded_constant_pool && constant_pool_address) {
391 *constant_pool_address = holder->constant_pool();
392 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000394}
395
396
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100397void StackFrame::SetReturnAddressLocationResolver(
398 ReturnAddressLocationResolver resolver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000399 DCHECK(return_address_location_resolver_ == NULL);
400 return_address_location_resolver_ = resolver;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100401}
402
403
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000404StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
405 State* state) {
406 DCHECK(state->fp != NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000407
408 if (!iterator->can_access_heap_objects_) {
409 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really
410 // means that we are being called from the profiler, which can interrupt
411 // the VM with a signal at any arbitrary instruction, with essentially
412 // anything on the stack. So basically none of these checks are 100%
413 // reliable.
414 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
415 // An adapter frame has a special SMI constant for the context and
416 // is not distinguished through the marker.
417 return ARGUMENTS_ADAPTOR;
418 }
419 Object* marker =
420 Memory::Object_at(state->fp + StandardFrameConstants::kMarkerOffset);
421 if (marker->IsSmi()) {
422 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
423 } else {
424 return JAVA_SCRIPT;
425 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000427
428 // Look up the code object to figure out the type of the stack frame.
429 Code* code_obj = GetContainingCode(iterator->isolate(), *(state->pc_address));
430
431 Object* marker =
432 Memory::Object_at(state->fp + StandardFrameConstants::kMarkerOffset);
433 if (code_obj != nullptr) {
434 switch (code_obj->kind()) {
435 case Code::FUNCTION:
436 return JAVA_SCRIPT;
437 case Code::OPTIMIZED_FUNCTION:
438 return OPTIMIZED;
439 case Code::WASM_FUNCTION:
440 return STUB;
441 case Code::BUILTIN:
442 if (!marker->IsSmi()) {
443 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
444 // An adapter frame has a special SMI constant for the context and
445 // is not distinguished through the marker.
446 return ARGUMENTS_ADAPTOR;
447 } else {
448 // The interpreter entry trampoline has a non-SMI marker.
449 DCHECK(code_obj->is_interpreter_entry_trampoline());
450 return INTERPRETED;
451 }
452 }
453 break; // Marker encodes the frame type.
454 case Code::HANDLER:
455 if (!marker->IsSmi()) {
456 // Only hydrogen code stub handlers can have a non-SMI marker.
457 DCHECK(code_obj->is_hydrogen_stub());
458 return OPTIMIZED;
459 }
460 break; // Marker encodes the frame type.
461 default:
462 break; // Marker encodes the frame type.
463 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100464 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000465
466 // Didn't find a code object, or the code kind wasn't specific enough.
467 // The marker should encode the frame type.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100468 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000469}
470
471
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000472#ifdef DEBUG
473bool StackFrame::can_access_heap_objects() const {
474 return iterator_->can_access_heap_objects_;
475}
476#endif
477
Steve Blocka7e24c12009-10-30 11:49:00 +0000478
479StackFrame::Type StackFrame::GetCallerState(State* state) const {
480 ComputeCallerState(state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481 return ComputeType(iterator_, state);
482}
483
484
485Address StackFrame::UnpaddedFP() const {
486#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
487 if (!is_optimized()) return fp();
488 int32_t alignment_state = Memory::int32_at(
489 fp() + JavaScriptFrameConstants::kDynamicAlignmentStateOffset);
490
491 return (alignment_state == kAlignmentPaddingPushed) ?
492 (fp() + kPointerSize) : fp();
493#else
494 return fp();
495#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000496}
497
498
Iain Merrick75681382010-08-19 15:07:18 +0100499Code* EntryFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500 return isolate()->heap()->js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000501}
502
503
504void EntryFrame::ComputeCallerState(State* state) const {
505 GetCallerState(state);
506}
507
508
Steve Block6ded16b2010-05-10 14:33:55 +0100509void EntryFrame::SetCallerFp(Address caller_fp) {
510 const int offset = EntryFrameConstants::kCallerFPOffset;
511 Memory::Address_at(this->fp() + offset) = caller_fp;
512}
513
514
Steve Blocka7e24c12009-10-30 11:49:00 +0000515StackFrame::Type EntryFrame::GetCallerState(State* state) const {
516 const int offset = EntryFrameConstants::kCallerFPOffset;
517 Address fp = Memory::Address_at(this->fp() + offset);
518 return ExitFrame::GetStateForFramePointer(fp, state);
519}
520
521
Iain Merrick75681382010-08-19 15:07:18 +0100522Code* EntryConstructFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523 return isolate()->heap()->js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000524}
525
526
Steve Blockd0582a62009-12-15 09:54:21 +0000527Object*& ExitFrame::code_slot() const {
528 const int offset = ExitFrameConstants::kCodeOffset;
529 return Memory::Object_at(fp() + offset);
530}
531
532
Iain Merrick75681382010-08-19 15:07:18 +0100533Code* ExitFrame::unchecked_code() const {
534 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000535}
536
537
538void ExitFrame::ComputeCallerState(State* state) const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100539 // Set up the caller state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000540 state->sp = caller_sp();
541 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100542 state->pc_address = ResolveReturnAddressLocation(
543 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000544 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000545 state->constant_pool_address = reinterpret_cast<Address*>(
546 fp() + ExitFrameConstants::kConstantPoolOffset);
547 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000548}
549
550
Steve Block6ded16b2010-05-10 14:33:55 +0100551void ExitFrame::SetCallerFp(Address caller_fp) {
552 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
553}
554
555
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100556void ExitFrame::Iterate(ObjectVisitor* v) const {
557 // The arguments are traversed as part of the expression stack of
558 // the calling frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000559 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100560 v->VisitPointer(&code_slot());
561}
562
563
Steve Blocka7e24c12009-10-30 11:49:00 +0000564Address ExitFrame::GetCallerStackPointer() const {
565 return fp() + ExitFrameConstants::kCallerSPDisplacement;
566}
567
568
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100569StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
570 if (fp == 0) return NONE;
571 Address sp = ComputeStackPointer(fp);
572 FillState(fp, sp, state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 DCHECK(*state->pc_address != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100574 return EXIT;
575}
576
577
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578Address ExitFrame::ComputeStackPointer(Address fp) {
579 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
580}
581
582
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100583void ExitFrame::FillState(Address fp, Address sp, State* state) {
584 state->sp = sp;
585 state->fp = fp;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100586 state->pc_address = ResolveReturnAddressLocation(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588 // The constant pool recorded in the exit frame is not associated
589 // with the pc in this state (the return address into a C entry
590 // stub). ComputeCallerState will retrieve the constant pool
591 // together with the associated caller pc.
592 state->constant_pool_address = NULL;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100593}
594
595
Steve Blocka7e24c12009-10-30 11:49:00 +0000596Address StandardFrame::GetExpressionAddress(int n) const {
597 const int offset = StandardFrameConstants::kExpressionsOffset;
598 return fp() + offset - n * kPointerSize;
599}
600
601
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000602Object* StandardFrame::GetExpression(Address fp, int index) {
603 return Memory::Object_at(GetExpressionAddress(fp, index));
604}
605
606
607Address StandardFrame::GetExpressionAddress(Address fp, int n) {
608 const int offset = StandardFrameConstants::kExpressionsOffset;
609 return fp + offset - n * kPointerSize;
610}
611
612
Steve Blocka7e24c12009-10-30 11:49:00 +0000613int StandardFrame::ComputeExpressionsCount() const {
614 const int offset =
615 StandardFrameConstants::kExpressionsOffset + kPointerSize;
616 Address base = fp() + offset;
617 Address limit = sp();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000618 DCHECK(base >= limit); // stack grows downwards
Steve Blocka7e24c12009-10-30 11:49:00 +0000619 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000620 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000621}
622
623
624void StandardFrame::ComputeCallerState(State* state) const {
625 state->sp = caller_sp();
626 state->fp = caller_fp();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100627 state->pc_address = ResolveReturnAddressLocation(
628 reinterpret_cast<Address*>(ComputePCAddress(fp())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 state->constant_pool_address =
630 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000631}
632
633
Steve Block6ded16b2010-05-10 14:33:55 +0100634void StandardFrame::SetCallerFp(Address caller_fp) {
635 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
636 caller_fp;
637}
638
639
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000640void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100641 // Make sure that we're not doing "safe" stack frame iteration. We cannot
642 // possibly find pointers in optimized frames in that state.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000643 DCHECK(can_access_heap_objects());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100644
645 // Compute the safepoint information.
646 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100647 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100648 Code* code = StackFrame::GetSafepointData(
Ben Murdoch8b112d22011-06-08 16:22:53 +0100649 isolate(), pc(), &safepoint_entry, &stack_slots);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100650 unsigned slot_space = stack_slots * kPointerSize;
651
Ben Murdoch8b112d22011-06-08 16:22:53 +0100652 // Visit the outgoing parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100653 Object** parameters_base = &Memory::Object_at(sp());
654 Object** parameters_limit = &Memory::Object_at(
655 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
656
Ben Murdochb8e0da22011-05-16 14:20:40 +0100657 // Visit the parameters that may be on top of the saved registers.
658 if (safepoint_entry.argument_count() > 0) {
659 v->VisitPointers(parameters_base,
660 parameters_base + safepoint_entry.argument_count());
661 parameters_base += safepoint_entry.argument_count();
662 }
663
664 // Skip saved double registers.
665 if (safepoint_entry.has_doubles()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000666 // Number of doubles not known at snapshot time.
667 DCHECK(!isolate()->serializer_enabled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 parameters_base +=
669 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
670 ->num_allocatable_double_registers() *
Ben Murdochb8e0da22011-05-16 14:20:40 +0100671 kDoubleSize / kPointerSize;
672 }
673
Ben Murdochb0fe1622011-05-05 13:52:32 +0100674 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100675 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100676 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100677 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100678 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
679 v->VisitPointer(parameters_base + reg_stack_index);
680 }
681 }
682 // Skip the words containing the register values.
683 parameters_base += kNumSafepointRegisters;
684 }
685
686 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100687 uint8_t* safepoint_bits = safepoint_entry.bits();
688 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100689
690 // Visit the rest of the parameters.
691 v->VisitPointers(parameters_base, parameters_limit);
692
693 // Visit pointer spill slots and locals.
694 for (unsigned index = 0; index < stack_slots; index++) {
695 int byte_index = index >> kBitsPerByteLog2;
696 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100697 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100698 v->VisitPointer(parameters_limit + index);
699 }
700 }
701
Ben Murdochb0fe1622011-05-05 13:52:32 +0100702 // Visit the return address in the callee and incoming arguments.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000703 IteratePc(v, pc_address(), constant_pool_address(), code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000704
705 // Visit the context in stub frame and JavaScript frame.
706 // Visit the function in JavaScript frame.
707 Object** fixed_base = &Memory::Object_at(
708 fp() + StandardFrameConstants::kMarkerOffset);
709 Object** fixed_limit = &Memory::Object_at(fp());
710 v->VisitPointers(fixed_base, fixed_limit);
711}
712
713
714void StubFrame::Iterate(ObjectVisitor* v) const {
715 IterateCompiledFrame(v);
716}
717
718
719Code* StubFrame::unchecked_code() const {
720 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
721}
722
723
724Address StubFrame::GetCallerStackPointer() const {
725 return fp() + ExitFrameConstants::kCallerSPDisplacement;
726}
727
728
729int StubFrame::GetNumberOfIncomingArguments() const {
730 return 0;
731}
732
733
734void OptimizedFrame::Iterate(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000735 IterateCompiledFrame(v);
736}
737
738
739void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
740 Memory::Object_at(GetParameterSlot(index)) = value;
Steve Blocka7e24c12009-10-30 11:49:00 +0000741}
742
743
744bool JavaScriptFrame::IsConstructor() const {
745 Address fp = caller_fp();
746 if (has_adapted_arguments()) {
747 // Skip the arguments adaptor frame and look at the real caller.
748 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
749 }
750 return IsConstructFrame(fp);
751}
752
753
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000754bool JavaScriptFrame::HasInlinedFrames() const {
755 List<JSFunction*> functions(1);
756 GetFunctions(&functions);
757 return functions.length() > 1;
758}
759
760
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000761int JavaScriptFrame::GetArgumentsLength() const {
762 // If there is an arguments adaptor frame get the arguments length from it.
763 if (has_adapted_arguments()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000764 STATIC_ASSERT(ArgumentsAdaptorFrameConstants::kLengthOffset ==
765 StandardFrameConstants::kExpressionsOffset);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000766 return Smi::cast(GetExpression(caller_fp(), 0))->value();
767 } else {
768 return GetNumberOfIncomingArguments();
769 }
770}
771
772
Iain Merrick75681382010-08-19 15:07:18 +0100773Code* JavaScriptFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000774 return function()->code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000775}
776
777
Ben Murdoch8b112d22011-06-08 16:22:53 +0100778int JavaScriptFrame::GetNumberOfIncomingArguments() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000779 DCHECK(can_access_heap_objects() &&
Ben Murdoch8b112d22011-06-08 16:22:53 +0100780 isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
781
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000782 return function()->shared()->internal_formal_parameter_count();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100783}
784
785
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100786Address JavaScriptFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100787 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100788}
789
790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000791void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000792 DCHECK(functions->length() == 0);
793 functions->Add(function());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100794}
795
796
797void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000798 DCHECK(functions->length() == 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100799 Code* code_pointer = LookupCode();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100800 int offset = static_cast<int>(pc() - code_pointer->address());
801 FrameSummary summary(receiver(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000802 function(),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100803 code_pointer,
804 offset,
805 IsConstructor());
806 functions->Add(summary);
807}
808
809
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000810int JavaScriptFrame::LookupExceptionHandlerInTable(
811 int* stack_slots, HandlerTable::CatchPrediction* prediction) {
812 Code* code = LookupCode();
813 DCHECK(!code->is_optimized_code());
814 HandlerTable* table = HandlerTable::cast(code->handler_table());
815 int pc_offset = static_cast<int>(pc() - code->entry());
816 return table->LookupRange(pc_offset, stack_slots, prediction);
817}
818
819
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000820void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
821 Address pc, FILE* file,
822 bool print_line_number) {
823 PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
824 function->PrintName(file);
825 int code_offset = static_cast<int>(pc - code->instruction_start());
826 PrintF(file, "+%d", code_offset);
827 if (print_line_number) {
828 SharedFunctionInfo* shared = function->shared();
829 int source_pos = code->SourcePosition(pc);
830 Object* maybe_script = shared->script();
831 if (maybe_script->IsScript()) {
832 Script* script = Script::cast(maybe_script);
833 int line = script->GetLineNumber(source_pos) + 1;
834 Object* script_name_raw = script->name();
835 if (script_name_raw->IsString()) {
836 String* script_name = String::cast(script->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837 base::SmartArrayPointer<char> c_script_name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000838 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
839 PrintF(file, " at %s:%d", c_script_name.get(), line);
840 } else {
841 PrintF(file, " at <unknown>:%d", line);
842 }
843 } else {
844 PrintF(file, " at <unknown>:<unknown>");
845 }
846 }
847}
848
849
850void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100851 bool print_line_number) {
852 // constructor calls
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 DisallowHeapAllocation no_allocation;
854 JavaScriptFrameIterator it(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100855 while (!it.done()) {
856 if (it.frame()->is_java_script()) {
857 JavaScriptFrame* frame = it.frame();
858 if (frame->IsConstructor()) PrintF(file, "new ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000859 PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
860 frame->pc(), file, print_line_number);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100861 if (print_args) {
862 // function arguments
863 // (we are intentionally only printing the actually
864 // supplied parameters, not all parameters required)
865 PrintF(file, "(this=");
866 frame->receiver()->ShortPrint(file);
867 const int length = frame->ComputeParametersCount();
868 for (int i = 0; i < length; i++) {
869 PrintF(file, ", ");
870 frame->GetParameter(i)->ShortPrint(file);
871 }
872 PrintF(file, ")");
873 }
874 break;
875 }
876 it.Advance();
877 }
878}
879
880
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881void JavaScriptFrame::SaveOperandStack(FixedArray* store) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882 int operands_count = store->length();
883 DCHECK_LE(operands_count, ComputeOperandsCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000884 for (int i = 0; i < operands_count; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885 store->set(i, GetOperand(i));
886 }
887}
888
889
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000890void JavaScriptFrame::RestoreOperandStack(FixedArray* store) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 int operands_count = store->length();
892 DCHECK_LE(operands_count, ComputeOperandsCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000893 for (int i = 0; i < operands_count; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000894 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
895 Memory::Object_at(GetOperandSlot(i)) = store->get(i);
896 }
897}
898
899
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000900FrameSummary::FrameSummary(Object* receiver, JSFunction* function, Code* code,
901 int offset, bool is_constructor)
902 : receiver_(receiver, function->GetIsolate()),
903 function_(function),
904 code_(code),
905 offset_(offset),
906 is_constructor_(is_constructor) {}
907
908
Ben Murdochb0fe1622011-05-05 13:52:32 +0100909void FrameSummary::Print() {
910 PrintF("receiver: ");
911 receiver_->ShortPrint();
912 PrintF("\nfunction: ");
913 function_->shared()->DebugName()->ShortPrint();
914 PrintF("\ncode: ");
915 code_->ShortPrint();
916 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
917 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
918 PrintF("\npc: %d\n", offset_);
919}
920
921
922void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923 DCHECK(frames->length() == 0);
924 DCHECK(is_optimized());
925
926 // Delegate to JS frame in absence of turbofan deoptimization.
927 // TODO(turbofan): Revisit once we support deoptimization across the board.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000928 if (LookupCode()->is_turbofanned() && function()->shared()->asm_function() &&
929 !FLAG_turbo_asm_deoptimization) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000930 return JavaScriptFrame::Summarize(frames);
931 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100932
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000933 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +0100934 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000935 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
936 FixedArray* const literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100937
938 TranslationIterator it(data->TranslationByteArray(),
939 data->TranslationIndex(deopt_index)->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000940 Translation::Opcode frame_opcode =
941 static_cast<Translation::Opcode>(it.Next());
942 DCHECK_EQ(Translation::BEGIN, frame_opcode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100943 it.Next(); // Drop frame count.
944 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100945
946 // We create the summary in reverse order because the frames
947 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100948 bool is_constructor = IsConstructor();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 while (jsframe_count != 0) {
950 frame_opcode = static_cast<Translation::Opcode>(it.Next());
951 if (frame_opcode == Translation::JS_FRAME ||
952 frame_opcode == Translation::INTERPRETED_FRAME) {
953 jsframe_count--;
954 BailoutId const ast_id = BailoutId(it.Next());
955 SharedFunctionInfo* const shared_info =
956 SharedFunctionInfo::cast(literal_array->get(it.Next()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100957 it.Next(); // Skip height.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100958
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 // The translation commands are ordered and the function is always
960 // at the first position, and the receiver is next.
961 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
962
963 // Get the correct function in the optimized frame.
964 JSFunction* function;
965 if (opcode == Translation::LITERAL) {
966 function = JSFunction::cast(literal_array->get(it.Next()));
967 } else if (opcode == Translation::STACK_SLOT) {
968 function = JSFunction::cast(StackSlotAt(it.Next()));
969 } else {
970 CHECK_EQ(Translation::JS_FRAME_FUNCTION, opcode);
971 function = this->function();
972 }
973 DCHECK_EQ(shared_info, function->shared());
974
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975 // If we are at a call, the receiver is always in a stack slot.
976 // Otherwise we are not guaranteed to get the receiver value.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100977 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100978
979 // Get the correct receiver in the optimized frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980 Object* receiver;
Ben Murdoch257744e2011-11-30 15:57:28 +0000981 if (opcode == Translation::LITERAL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000982 receiver = literal_array->get(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000983 } else if (opcode == Translation::STACK_SLOT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000984 receiver = StackSlotAt(it.Next());
985 } else if (opcode == Translation::JS_FRAME_FUNCTION) {
986 receiver = this->function();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000987 } else {
988 // The receiver is not in a stack slot nor in a literal. We give up.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000989 it.Skip(Translation::NumberOfOperandsFor(opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000990 // TODO(3029): Materializing a captured object (or duplicated
991 // object) is hard, we return undefined for now. This breaks the
992 // produced stack trace, as constructor frames aren't marked as
993 // such anymore.
994 receiver = isolate()->heap()->undefined_value();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100995 }
996
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 Code* const code = shared_info->code();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100998
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 unsigned pc_offset;
1000 if (frame_opcode == Translation::JS_FRAME) {
1001 DeoptimizationOutputData* const output_data =
1002 DeoptimizationOutputData::cast(code->deoptimization_data());
1003 unsigned const entry =
1004 Deoptimizer::GetOutputInfo(output_data, ast_id, shared_info);
1005 pc_offset =
1006 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
1007 DCHECK_NE(0U, pc_offset);
1008 } else {
1009 // TODO(rmcilroy): Modify FrameSummary to enable us to summarize
1010 // based on the BytecodeArray and bytecode offset.
1011 DCHECK_EQ(frame_opcode, Translation::INTERPRETED_FRAME);
1012 pc_offset = 0;
1013 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001014 FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
1015 frames->Add(summary);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001016 is_constructor = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001017 } else if (frame_opcode == Translation::CONSTRUCT_STUB_FRAME) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001018 // The next encountered JS_FRAME will be marked as a constructor call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001019 it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001020 DCHECK(!is_constructor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001021 is_constructor = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001022 } else {
1023 // Skip over operands to advance to the next opcode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001024 it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001025 }
1026 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001027 DCHECK(!is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001028}
1029
1030
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001031int OptimizedFrame::LookupExceptionHandlerInTable(
1032 int* stack_slots, HandlerTable::CatchPrediction* prediction) {
1033 Code* code = LookupCode();
1034 DCHECK(code->is_optimized_code());
1035 HandlerTable* table = HandlerTable::cast(code->handler_table());
1036 int pc_offset = static_cast<int>(pc() - code->entry());
1037 *stack_slots = code->stack_slots();
1038 return table->LookupReturn(pc_offset, prediction);
1039}
1040
1041
Ben Murdochb0fe1622011-05-05 13:52:32 +01001042DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043 int* deopt_index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001044 DCHECK(is_optimized());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001045
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001046 JSFunction* opt_function = function();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001047 Code* code = opt_function->code();
1048
1049 // The code object may have been replaced by lazy deoptimization. Fall
1050 // back to a slow search in this case to find the original optimized
1051 // code object.
1052 if (!code->contains(pc())) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001053 code = isolate()->inner_pointer_to_code_cache()->
1054 GcSafeFindCodeForInnerPointer(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001055 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056 DCHECK(code != NULL);
1057 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001058
Ben Murdochb8e0da22011-05-16 14:20:40 +01001059 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1060 *deopt_index = safepoint_entry.deoptimization_index();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001061 DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001062
1063 return DeoptimizationInputData::cast(code->deoptimization_data());
1064}
1065
1066
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001067void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001068 DCHECK(functions->length() == 0);
1069 DCHECK(is_optimized());
1070
1071 // Delegate to JS frame in absence of turbofan deoptimization.
1072 // TODO(turbofan): Revisit once we support deoptimization across the board.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001073 if (LookupCode()->is_turbofanned() && function()->shared()->asm_function() &&
1074 !FLAG_turbo_asm_deoptimization) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001075 return JavaScriptFrame::GetFunctions(functions);
1076 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001077
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001078 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +01001079 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
1081 FixedArray* const literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001082
1083 TranslationIterator it(data->TranslationByteArray(),
1084 data->TranslationIndex(deopt_index)->value());
1085 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001086 DCHECK_EQ(Translation::BEGIN, opcode);
1087 it.Next(); // Skip frame count.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001088 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001089
1090 // We insert the frames in reverse order because the frames
1091 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001092 while (jsframe_count != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001093 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001094 // Skip over operands to advance to the next opcode.
1095 it.Skip(Translation::NumberOfOperandsFor(opcode));
1096 if (opcode == Translation::JS_FRAME ||
1097 opcode == Translation::INTERPRETED_FRAME) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001098 jsframe_count--;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001099
1100 // The translation commands are ordered and the function is always at the
1101 // first position.
1102 opcode = static_cast<Translation::Opcode>(it.Next());
1103
1104 // Get the correct function in the optimized frame.
1105 Object* function;
1106 if (opcode == Translation::LITERAL) {
1107 function = literal_array->get(it.Next());
1108 } else if (opcode == Translation::STACK_SLOT) {
1109 function = StackSlotAt(it.Next());
1110 } else {
1111 CHECK_EQ(Translation::JS_FRAME_FUNCTION, opcode);
1112 function = this->function();
1113 }
1114 functions->Add(JSFunction::cast(function));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001115 }
1116 }
1117}
1118
1119
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001120int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) {
1121 return StandardFrameConstants::kCallerSPOffset -
1122 ((slot_index + 1) * kPointerSize);
1123}
1124
1125
1126Object* OptimizedFrame::StackSlotAt(int index) const {
1127 return Memory::Object_at(fp() + StackSlotOffsetRelativeToFp(index));
1128}
1129
1130
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001131int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
1132 return Smi::cast(GetExpression(0))->value();
1133}
1134
1135
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001136Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001137 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001138}
1139
1140
1141Address InternalFrame::GetCallerStackPointer() const {
1142 // Internal frames have no arguments. The stack pointer of the
1143 // caller is at a fixed offset from the frame pointer.
1144 return fp() + StandardFrameConstants::kCallerSPOffset;
1145}
1146
1147
Iain Merrick75681382010-08-19 15:07:18 +01001148Code* ArgumentsAdaptorFrame::unchecked_code() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001149 return isolate()->builtins()->builtin(
Steve Block44f0eee2011-05-26 01:26:41 +01001150 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +00001151}
1152
1153
Iain Merrick75681382010-08-19 15:07:18 +01001154Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001155 const int offset = InternalFrameConstants::kCodeOffset;
1156 Object* code = Memory::Object_at(fp() + offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001157 DCHECK(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +01001158 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001159}
1160
1161
1162void StackFrame::PrintIndex(StringStream* accumulator,
1163 PrintMode mode,
1164 int index) {
1165 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1166}
1167
1168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001169namespace {
1170
1171
1172void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared,
1173 Code* code) {
1174 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1175 std::ostringstream os;
1176 os << "--------- s o u r c e c o d e ---------\n"
1177 << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1178 << "\n-----------------------------------------\n";
1179 accumulator->Add(os.str().c_str());
1180 }
1181}
1182
1183
1184} // namespace
1185
1186
Steve Blocka7e24c12009-10-30 11:49:00 +00001187void JavaScriptFrame::Print(StringStream* accumulator,
1188 PrintMode mode,
1189 int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001190 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001191 Object* receiver = this->receiver();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 JSFunction* function = this->function();
Steve Blocka7e24c12009-10-30 11:49:00 +00001193
1194 accumulator->PrintSecurityTokenIfChanged(function);
1195 PrintIndex(accumulator, mode, index);
1196 Code* code = NULL;
1197 if (IsConstructor()) accumulator->Add("new ");
1198 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +01001199
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001200 // Get scope information for nicer output, if possible. If code is NULL, or
1201 // doesn't contain scope info, scope_info will return 0 for the number of
1202 // parameters, stack local variables, context local variables, stack slots,
1203 // or context slots.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001204 SharedFunctionInfo* shared = function->shared();
1205 ScopeInfo* scope_info = shared->scope_info();
1206 Object* script_obj = shared->script();
1207 if (script_obj->IsScript()) {
1208 Script* script = Script::cast(script_obj);
1209 accumulator->Add(" [");
1210 accumulator->PrintName(script->name());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001211
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001212 Address pc = this->pc();
1213 if (code != NULL && code->kind() == Code::FUNCTION &&
1214 pc >= code->instruction_start() && pc < code->instruction_end()) {
1215 int source_pos = code->SourcePosition(pc);
1216 int line = script->GetLineNumber(source_pos) + 1;
1217 accumulator->Add(":%d", line);
1218 } else {
1219 int function_start_pos = shared->start_position();
1220 int line = script->GetLineNumber(function_start_pos) + 1;
1221 accumulator->Add(":~%d", line);
Steve Block6ded16b2010-05-10 14:33:55 +01001222 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001224 accumulator->Add("] [pc=%p] ", pc);
Steve Block6ded16b2010-05-10 14:33:55 +01001225 }
1226
Steve Blocka7e24c12009-10-30 11:49:00 +00001227 accumulator->Add("(this=%o", receiver);
1228
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 // Print the parameters.
1230 int parameters_count = ComputeParametersCount();
1231 for (int i = 0; i < parameters_count; i++) {
1232 accumulator->Add(",");
1233 // If we have a name for the parameter we print it. Nameless
1234 // parameters are either because we have more actual parameters
1235 // than formal parameters or because we have no scope information.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001236 if (i < scope_info->ParameterCount()) {
1237 accumulator->PrintName(scope_info->ParameterName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 accumulator->Add("=");
1239 }
1240 accumulator->Add("%o", GetParameter(i));
1241 }
1242
1243 accumulator->Add(")");
1244 if (mode == OVERVIEW) {
1245 accumulator->Add("\n");
1246 return;
1247 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001248 if (is_optimized()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001249 accumulator->Add(" {\n// optimized frame\n");
1250 PrintFunctionSource(accumulator, shared, code);
1251 accumulator->Add("}\n");
Ben Murdoch257744e2011-11-30 15:57:28 +00001252 return;
1253 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001254 accumulator->Add(" {\n");
1255
1256 // Compute the number of locals and expression stack elements.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001257 int stack_locals_count = scope_info->StackLocalCount();
1258 int heap_locals_count = scope_info->ContextLocalCount();
Steve Blocka7e24c12009-10-30 11:49:00 +00001259 int expressions_count = ComputeExpressionsCount();
1260
1261 // Print stack-allocated local variables.
1262 if (stack_locals_count > 0) {
1263 accumulator->Add(" // stack-allocated locals\n");
1264 }
1265 for (int i = 0; i < stack_locals_count; i++) {
1266 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001267 accumulator->PrintName(scope_info->StackLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001268 accumulator->Add(" = ");
1269 if (i < expressions_count) {
1270 accumulator->Add("%o", GetExpression(i));
1271 } else {
1272 accumulator->Add("// no expression found - inconsistent frame?");
1273 }
1274 accumulator->Add("\n");
1275 }
1276
1277 // Try to get hold of the context of this frame.
1278 Context* context = NULL;
1279 if (this->context() != NULL && this->context()->IsContext()) {
1280 context = Context::cast(this->context());
1281 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001282 while (context->IsWithContext()) {
1283 context = context->previous();
1284 DCHECK(context != NULL);
1285 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001286
1287 // Print heap-allocated local variables.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001288 if (heap_locals_count > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001289 accumulator->Add(" // heap-allocated locals\n");
1290 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001291 for (int i = 0; i < heap_locals_count; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001292 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001293 accumulator->PrintName(scope_info->ContextLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001294 accumulator->Add(" = ");
1295 if (context != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001296 int index = Context::MIN_CONTEXT_SLOTS + i;
1297 if (index < context->length()) {
1298 accumulator->Add("%o", context->get(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00001299 } else {
1300 accumulator->Add(
1301 "// warning: missing context slot - inconsistent frame?");
1302 }
1303 } else {
1304 accumulator->Add("// warning: no context found - inconsistent frame?");
1305 }
1306 accumulator->Add("\n");
1307 }
1308
1309 // Print the expression stack.
1310 int expressions_start = stack_locals_count;
1311 if (expressions_start < expressions_count) {
1312 accumulator->Add(" // expression stack (top to bottom)\n");
1313 }
1314 for (int i = expressions_count - 1; i >= expressions_start; i--) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001315 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1316 }
1317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001318 PrintFunctionSource(accumulator, shared, code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001319
1320 accumulator->Add("}\n\n");
1321}
1322
1323
1324void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1325 PrintMode mode,
1326 int index) const {
1327 int actual = ComputeParametersCount();
1328 int expected = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001329 JSFunction* function = this->function();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001330 expected = function->shared()->internal_formal_parameter_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00001331
1332 PrintIndex(accumulator, mode, index);
1333 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1334 if (mode == OVERVIEW) {
1335 accumulator->Add("\n");
1336 return;
1337 }
1338 accumulator->Add(" {\n");
1339
1340 // Print actual arguments.
1341 if (actual > 0) accumulator->Add(" // actual arguments\n");
1342 for (int i = 0; i < actual; i++) {
1343 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1344 if (expected != -1 && i >= expected) {
1345 accumulator->Add(" // not passed to callee");
1346 }
1347 accumulator->Add("\n");
1348 }
1349
1350 accumulator->Add("}\n\n");
1351}
1352
1353
1354void EntryFrame::Iterate(ObjectVisitor* v) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001355 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001356}
1357
1358
1359void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001360 const int offset = StandardFrameConstants::kLastObjectOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +00001361 Object** base = &Memory::Object_at(sp());
1362 Object** limit = &Memory::Object_at(fp() + offset) + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00001363 v->VisitPointers(base, limit);
1364}
1365
1366
1367void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1368 IterateExpressions(v);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001370}
1371
1372
1373void InternalFrame::Iterate(ObjectVisitor* v) const {
1374 // Internal frames only have object pointers on the expression stack
1375 // as they never have any arguments.
1376 IterateExpressions(v);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001377 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001378}
1379
1380
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001381void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
1382 Object** base = &Memory::Object_at(sp());
1383 Object** limit = &Memory::Object_at(fp() +
1384 kFirstRegisterParameterFrameOffset);
1385 v->VisitPointers(base, limit);
1386 base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset);
1387 const int offset = StandardFrameConstants::kLastObjectOffset;
1388 limit = &Memory::Object_at(fp() + offset) + 1;
1389 v->VisitPointers(base, limit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001390 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001391}
1392
1393
1394Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
1395 return fp() + StandardFrameConstants::kCallerSPOffset;
1396}
1397
1398
1399Code* StubFailureTrampolineFrame::unchecked_code() const {
1400 Code* trampoline;
1401 StubFailureTrampolineStub(isolate(), NOT_JS_FUNCTION_STUB_MODE).
1402 FindCodeInCache(&trampoline);
1403 if (trampoline->contains(pc())) {
1404 return trampoline;
1405 }
1406
1407 StubFailureTrampolineStub(isolate(), JS_FUNCTION_STUB_MODE).
1408 FindCodeInCache(&trampoline);
1409 if (trampoline->contains(pc())) {
1410 return trampoline;
1411 }
1412
1413 UNREACHABLE();
1414 return NULL;
1415}
1416
1417
Steve Blocka7e24c12009-10-30 11:49:00 +00001418// -------------------------------------------------------------------------
1419
1420
1421JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001422 DCHECK(n >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001423 for (int i = 0; i <= n; i++) {
1424 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1425 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1426 iterator_.Advance();
1427 }
1428 UNREACHABLE();
1429 return NULL;
1430}
1431
1432
1433// -------------------------------------------------------------------------
1434
1435
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001436static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1437 MapWord map_word = object->map_word();
1438 return map_word.IsForwardingAddress() ?
1439 map_word.ToForwardingAddress()->map() : map_word.ToMap();
1440}
1441
1442
1443static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1444 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1445}
1446
1447
1448#ifdef DEBUG
1449static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1450 Map* map = GcSafeMapOfCodeSpaceObject(code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001451 DCHECK(map == code->GetHeap()->code_map());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001452 Address start = code->address();
1453 Address end = code->address() + code->SizeFromMap(map);
1454 return start <= addr && addr < end;
1455}
1456#endif
1457
1458
1459Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1460 Address inner_pointer) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001461 Code* code = reinterpret_cast<Code*>(object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001462 DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001463 return code;
1464}
1465
1466
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001467Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1468 Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001469 Heap* heap = isolate_->heap();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001470 if (!heap->code_space()->Contains(inner_pointer) &&
1471 !heap->lo_space()->Contains(inner_pointer)) {
1472 return nullptr;
1473 }
1474
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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001485 DCHECK_EQ(page->owner(), heap->code_space());
1486 heap->mark_compact_collector()->SweepOrWaitUntilSweepingCompleted(page);
1487
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001488 Address addr = page->skip_list()->StartFor(inner_pointer);
1489
1490 Address top = heap->code_space()->top();
1491 Address limit = heap->code_space()->limit();
1492
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001493 while (true) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001494 if (addr == top && addr != limit) {
1495 addr = limit;
1496 continue;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001497 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001498
1499 HeapObject* obj = HeapObject::FromAddress(addr);
1500 int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1501 Address next_addr = addr + obj_size;
1502 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1503 addr = next_addr;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001504 }
1505}
1506
Ben Murdochb0fe1622011-05-05 13:52:32 +01001507
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001508InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1509 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001510 isolate_->counters()->pc_to_code()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001511 DCHECK(base::bits::IsPowerOfTwo32(kInnerPointerToCodeCacheSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001512 uint32_t hash = ComputeIntegerHash(ObjectAddressForHashing(inner_pointer),
1513 v8::internal::kZeroHashSeed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001514 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1515 InnerPointerToCodeCacheEntry* entry = cache(index);
1516 if (entry->inner_pointer == inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001517 isolate_->counters()->pc_to_code_cached()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001518 DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001519 } else {
1520 // Because this code may be interrupted by a profiling signal that
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001521 // also queries the cache, we cannot update inner_pointer before the code
1522 // has been set. Otherwise, we risk trying to use a cache entry before
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001523 // the code has been computed.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001524 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001525 entry->safepoint_entry.Reset();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001526 entry->inner_pointer = inner_pointer;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001527 }
1528 return entry;
1529}
1530
1531
1532// -------------------------------------------------------------------------
1533
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001534
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001535int NumRegs(RegList reglist) { return base::bits::CountPopulation(reglist); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001536
1537
1538struct JSCallerSavedCodeData {
Steve Block44f0eee2011-05-26 01:26:41 +01001539 int reg_code[kNumJSCallerSaved];
1540};
1541
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001542JSCallerSavedCodeData caller_saved_code_data;
Steve Block44f0eee2011-05-26 01:26:41 +01001543
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001544void SetUpJSCallerSavedCodeData() {
1545 int i = 0;
1546 for (int r = 0; r < kNumRegs; r++)
1547 if ((kJSCallerSaved & (1 << r)) != 0)
1548 caller_saved_code_data.reg_code[i++] = r;
1549
1550 DCHECK(i == kNumJSCallerSaved);
1551}
1552
Steve Block44f0eee2011-05-26 01:26:41 +01001553
1554int JSCallerSavedCode(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001555 DCHECK(0 <= n && n < kNumJSCallerSaved);
1556 return caller_saved_code_data.reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001557}
1558
1559
Steve Block6ded16b2010-05-10 14:33:55 +01001560#define DEFINE_WRAPPER(type, field) \
1561class field##_Wrapper : public ZoneObject { \
1562 public: /* NOLINT */ \
1563 field##_Wrapper(const field& original) : frame_(original) { \
1564 } \
1565 field frame_; \
1566};
1567STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1568#undef DEFINE_WRAPPER
1569
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001570static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
Steve Block6ded16b2010-05-10 14:33:55 +01001571#define FRAME_TYPE_CASE(type, field) \
1572 case StackFrame::type: { \
1573 field##_Wrapper* wrapper = \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001574 new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
Steve Block6ded16b2010-05-10 14:33:55 +01001575 return &wrapper->frame_; \
1576 }
1577
1578 switch (frame->type()) {
1579 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1580 default: UNREACHABLE();
1581 }
1582#undef FRAME_TYPE_CASE
1583 return NULL;
1584}
1585
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001586
1587Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
1588 ZoneList<StackFrame*> list(10, zone);
1589 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1590 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1591 list.Add(frame, zone);
Steve Block6ded16b2010-05-10 14:33:55 +01001592 }
1593 return list.ToVector();
1594}
1595
1596
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001597} // namespace internal
1598} // namespace v8