blob: 50a2e21a055d7a9d8f11442f6cfa024d555c71dc [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) \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100124 case StackFrame::type: \
125 return &field##_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000126
Steve Blocka7e24c12009-10-30 11:49:00 +0000127 switch (type) {
128 case StackFrame::NONE: return NULL;
129 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
130 default: break;
131 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100132 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000133
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);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100237 DCHECK(frame_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 Advance();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100239}
240
241
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
243 Address c_entry_fp = Isolate::c_entry_fp(top);
244 if (!IsValidExitFrame(c_entry_fp)) return false;
245 // There should be at least one JS_ENTRY stack handler.
246 Address handler = Isolate::handler(top);
247 if (handler == NULL) return false;
248 // Check that there are no js frames on top of the native frames.
249 return c_entry_fp < handler;
250}
251
252
253void SafeStackFrameIterator::AdvanceOneFrame() {
254 DCHECK(!done());
255 StackFrame* last_frame = frame_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000256 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257 // Before advancing to the next stack frame, perform pointer validity tests.
258 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
259 frame_ = NULL;
260 return;
261 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000262
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263 // Advance to the previous frame.
264 StackFrame::State state;
265 StackFrame::Type type = frame_->GetCallerState(&state);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100266 if (SingletonFor(type) == NULL) {
267 frame_ = NULL;
268 return;
269 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000270 frame_ = SingletonFor(type, &state);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100271 DCHECK(frame_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000272
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 // Check that we have actually moved to the previous frame in the stack.
274 if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
275 frame_ = NULL;
276 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000277}
278
279
280bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
281 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
282}
283
284
285bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
286 StackFrame::State state;
287 if (frame->is_entry() || frame->is_entry_construct()) {
288 // See EntryFrame::GetCallerState. It computes the caller FP address
289 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
290 // sure that caller FP address is valid.
291 Address caller_fp = Memory::Address_at(
292 frame->fp() + EntryFrameConstants::kCallerFPOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 if (!IsValidExitFrame(caller_fp)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000294 } else if (frame->is_arguments_adaptor()) {
295 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
296 // the number of arguments is stored on stack as Smi. We need to check
297 // that it really an Smi.
298 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
299 GetExpression(0);
300 if (!number_of_args->IsSmi()) {
301 return false;
302 }
303 }
304 frame->ComputeCallerState(&state);
305 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306 SingletonFor(frame->GetCallerState(&state)) != NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000307}
308
309
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
311 if (!IsValidStackAddress(fp)) return false;
312 Address sp = ExitFrame::ComputeStackPointer(fp);
313 if (!IsValidStackAddress(sp)) return false;
314 StackFrame::State state;
315 ExitFrame::FillState(fp, sp, &state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000316 return *state.pc_address != NULL;
317}
318
319
320void SafeStackFrameIterator::Advance() {
321 while (true) {
322 AdvanceOneFrame();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100323 if (done()) break;
324 ExternalCallbackScope* last_callback_scope = NULL;
325 while (external_callback_scope_ != NULL &&
326 external_callback_scope_->scope_address() < frame_->fp()) {
327 // As long as the setup of a frame is not atomic, we may happen to be
328 // in an interval where an ExternalCallbackScope is already created,
329 // but the frame is not yet entered. So we are actually observing
330 // the previous frame.
331 // Skip all the ExternalCallbackScope's that are below the current fp.
332 last_callback_scope = external_callback_scope_;
333 external_callback_scope_ = external_callback_scope_->previous();
334 }
335 if (frame_->is_java_script()) break;
336 if (frame_->is_exit()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337 // 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.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100342 if (last_callback_scope) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343 frame_->state_.pc_address =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100344 last_callback_scope->callback_entrypoint_address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100346 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000348 }
349}
350
351
352// -------------------------------------------------------------------------
353
354
Ben Murdoch8b112d22011-06-08 16:22:53 +0100355Code* StackFrame::GetSafepointData(Isolate* isolate,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100356 Address inner_pointer,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100357 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100358 unsigned* stack_slots) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100359 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
360 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100361 if (!entry->safepoint_entry.is_valid()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100362 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 DCHECK(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100364 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365 DCHECK(entry->safepoint_entry.Equals(
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100366 entry->code->GetSafepointEntry(inner_pointer)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100367 }
368
369 // Fill in the results and return the code.
370 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100371 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100372 *stack_slots = code->stack_slots();
373 return code;
374}
375
376
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100377#ifdef DEBUG
378static bool GcSafeCodeContains(HeapObject* object, Address addr);
379#endif
380
381
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382void StackFrame::IteratePc(ObjectVisitor* v, Address* pc_address,
383 Address* constant_pool_address, Code* holder) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100384 Address pc = *pc_address;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000385 DCHECK(GcSafeCodeContains(holder, pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100386 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
387 Object* code = holder;
388 v->VisitPointer(&code);
389 if (code != holder) {
390 holder = reinterpret_cast<Code*>(code);
391 pc = holder->instruction_start() + pc_offset;
392 *pc_address = pc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000393 if (FLAG_enable_embedded_constant_pool && constant_pool_address) {
394 *constant_pool_address = holder->constant_pool();
395 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000396 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000397}
398
399
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100400void StackFrame::SetReturnAddressLocationResolver(
401 ReturnAddressLocationResolver resolver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000402 DCHECK(return_address_location_resolver_ == NULL);
403 return_address_location_resolver_ = resolver;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100404}
405
406
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
408 State* state) {
409 DCHECK(state->fp != NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410
411 if (!iterator->can_access_heap_objects_) {
412 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really
413 // means that we are being called from the profiler, which can interrupt
414 // the VM with a signal at any arbitrary instruction, with essentially
415 // anything on the stack. So basically none of these checks are 100%
416 // reliable.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100417#if defined(USE_SIMULATOR)
418 MSAN_MEMORY_IS_INITIALIZED(
419 state->fp + StandardFrameConstants::kContextOffset, kPointerSize);
420 MSAN_MEMORY_IS_INITIALIZED(
421 state->fp + StandardFrameConstants::kMarkerOffset, kPointerSize);
422#endif
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000423 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
424 // An adapter frame has a special SMI constant for the context and
425 // is not distinguished through the marker.
426 return ARGUMENTS_ADAPTOR;
427 }
428 Object* marker =
429 Memory::Object_at(state->fp + StandardFrameConstants::kMarkerOffset);
430 if (marker->IsSmi()) {
431 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
432 } else {
433 return JAVA_SCRIPT;
434 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000435 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436
437 // Look up the code object to figure out the type of the stack frame.
438 Code* code_obj = GetContainingCode(iterator->isolate(), *(state->pc_address));
439
440 Object* marker =
441 Memory::Object_at(state->fp + StandardFrameConstants::kMarkerOffset);
442 if (code_obj != nullptr) {
443 switch (code_obj->kind()) {
444 case Code::FUNCTION:
445 return JAVA_SCRIPT;
446 case Code::OPTIMIZED_FUNCTION:
447 return OPTIMIZED;
448 case Code::WASM_FUNCTION:
449 return STUB;
450 case Code::BUILTIN:
451 if (!marker->IsSmi()) {
452 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
453 // An adapter frame has a special SMI constant for the context and
454 // is not distinguished through the marker.
455 return ARGUMENTS_ADAPTOR;
456 } else {
457 // The interpreter entry trampoline has a non-SMI marker.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100458 DCHECK(code_obj->is_interpreter_entry_trampoline() ||
459 code_obj->is_interpreter_enter_bytecode_dispatch());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 return INTERPRETED;
461 }
462 }
463 break; // Marker encodes the frame type.
464 case Code::HANDLER:
465 if (!marker->IsSmi()) {
466 // Only hydrogen code stub handlers can have a non-SMI marker.
467 DCHECK(code_obj->is_hydrogen_stub());
468 return OPTIMIZED;
469 }
470 break; // Marker encodes the frame type.
471 default:
472 break; // Marker encodes the frame type.
473 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100474 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475
476 // Didn't find a code object, or the code kind wasn't specific enough.
477 // The marker should encode the frame type.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100478 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000479}
480
481
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000482#ifdef DEBUG
483bool StackFrame::can_access_heap_objects() const {
484 return iterator_->can_access_heap_objects_;
485}
486#endif
487
Steve Blocka7e24c12009-10-30 11:49:00 +0000488
489StackFrame::Type StackFrame::GetCallerState(State* state) const {
490 ComputeCallerState(state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000491 return ComputeType(iterator_, state);
492}
493
494
495Address StackFrame::UnpaddedFP() const {
496#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
497 if (!is_optimized()) return fp();
498 int32_t alignment_state = Memory::int32_at(
499 fp() + JavaScriptFrameConstants::kDynamicAlignmentStateOffset);
500
501 return (alignment_state == kAlignmentPaddingPushed) ?
502 (fp() + kPointerSize) : fp();
503#else
504 return fp();
505#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000506}
507
508
Iain Merrick75681382010-08-19 15:07:18 +0100509Code* EntryFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 return isolate()->heap()->js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000511}
512
513
514void EntryFrame::ComputeCallerState(State* state) const {
515 GetCallerState(state);
516}
517
518
Steve Block6ded16b2010-05-10 14:33:55 +0100519void EntryFrame::SetCallerFp(Address caller_fp) {
520 const int offset = EntryFrameConstants::kCallerFPOffset;
521 Memory::Address_at(this->fp() + offset) = caller_fp;
522}
523
524
Steve Blocka7e24c12009-10-30 11:49:00 +0000525StackFrame::Type EntryFrame::GetCallerState(State* state) const {
526 const int offset = EntryFrameConstants::kCallerFPOffset;
527 Address fp = Memory::Address_at(this->fp() + offset);
528 return ExitFrame::GetStateForFramePointer(fp, state);
529}
530
531
Iain Merrick75681382010-08-19 15:07:18 +0100532Code* EntryConstructFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533 return isolate()->heap()->js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000534}
535
536
Steve Blockd0582a62009-12-15 09:54:21 +0000537Object*& ExitFrame::code_slot() const {
538 const int offset = ExitFrameConstants::kCodeOffset;
539 return Memory::Object_at(fp() + offset);
540}
541
542
Iain Merrick75681382010-08-19 15:07:18 +0100543Code* ExitFrame::unchecked_code() const {
544 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000545}
546
547
548void ExitFrame::ComputeCallerState(State* state) const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100549 // Set up the caller state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000550 state->sp = caller_sp();
551 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100552 state->pc_address = ResolveReturnAddressLocation(
553 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 state->constant_pool_address = reinterpret_cast<Address*>(
556 fp() + ExitFrameConstants::kConstantPoolOffset);
557 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000558}
559
560
Steve Block6ded16b2010-05-10 14:33:55 +0100561void ExitFrame::SetCallerFp(Address caller_fp) {
562 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
563}
564
565
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100566void ExitFrame::Iterate(ObjectVisitor* v) const {
567 // The arguments are traversed as part of the expression stack of
568 // the calling frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100570 v->VisitPointer(&code_slot());
571}
572
573
Steve Blocka7e24c12009-10-30 11:49:00 +0000574Address ExitFrame::GetCallerStackPointer() const {
575 return fp() + ExitFrameConstants::kCallerSPDisplacement;
576}
577
578
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100579StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
580 if (fp == 0) return NONE;
581 Address sp = ComputeStackPointer(fp);
582 FillState(fp, sp, state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 DCHECK(*state->pc_address != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100584 return EXIT;
585}
586
587
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000588Address ExitFrame::ComputeStackPointer(Address fp) {
589 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
590}
591
592
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100593void ExitFrame::FillState(Address fp, Address sp, State* state) {
594 state->sp = sp;
595 state->fp = fp;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100596 state->pc_address = ResolveReturnAddressLocation(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000597 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000598 // The constant pool recorded in the exit frame is not associated
599 // with the pc in this state (the return address into a C entry
600 // stub). ComputeCallerState will retrieve the constant pool
601 // together with the associated caller pc.
602 state->constant_pool_address = NULL;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100603}
604
605
Steve Blocka7e24c12009-10-30 11:49:00 +0000606Address StandardFrame::GetExpressionAddress(int n) const {
607 const int offset = StandardFrameConstants::kExpressionsOffset;
608 return fp() + offset - n * kPointerSize;
609}
610
Ben Murdoch097c5b22016-05-18 11:27:45 +0100611Address InterpretedFrame::GetExpressionAddress(int n) const {
612 const int offset = InterpreterFrameConstants::kExpressionsOffset;
613 return fp() + offset - n * kPointerSize;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000614}
615
Steve Blocka7e24c12009-10-30 11:49:00 +0000616int StandardFrame::ComputeExpressionsCount() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100617 Address base = GetExpressionAddress(0);
618 Address limit = sp() - kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619 DCHECK(base >= limit); // stack grows downwards
Steve Blocka7e24c12009-10-30 11:49:00 +0000620 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000621 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000622}
623
624
625void StandardFrame::ComputeCallerState(State* state) const {
626 state->sp = caller_sp();
627 state->fp = caller_fp();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100628 state->pc_address = ResolveReturnAddressLocation(
629 reinterpret_cast<Address*>(ComputePCAddress(fp())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000630 state->constant_pool_address =
631 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000632}
633
634
Steve Block6ded16b2010-05-10 14:33:55 +0100635void StandardFrame::SetCallerFp(Address caller_fp) {
636 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
637 caller_fp;
638}
639
640
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100642 // Make sure that we're not doing "safe" stack frame iteration. We cannot
643 // possibly find pointers in optimized frames in that state.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000644 DCHECK(can_access_heap_objects());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100645
646 // Compute the safepoint information.
647 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100648 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100649 Code* code = StackFrame::GetSafepointData(
Ben Murdoch8b112d22011-06-08 16:22:53 +0100650 isolate(), pc(), &safepoint_entry, &stack_slots);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100651 unsigned slot_space =
652 stack_slots * kPointerSize - StandardFrameConstants::kFixedFrameSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100653
Ben Murdoch8b112d22011-06-08 16:22:53 +0100654 // Visit the outgoing parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100655 Object** parameters_base = &Memory::Object_at(sp());
656 Object** parameters_limit = &Memory::Object_at(
657 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
658
Ben Murdochb8e0da22011-05-16 14:20:40 +0100659 // Visit the parameters that may be on top of the saved registers.
660 if (safepoint_entry.argument_count() > 0) {
661 v->VisitPointers(parameters_base,
662 parameters_base + safepoint_entry.argument_count());
663 parameters_base += safepoint_entry.argument_count();
664 }
665
666 // Skip saved double registers.
667 if (safepoint_entry.has_doubles()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668 // Number of doubles not known at snapshot time.
669 DCHECK(!isolate()->serializer_enabled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670 parameters_base +=
671 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
672 ->num_allocatable_double_registers() *
Ben Murdochb8e0da22011-05-16 14:20:40 +0100673 kDoubleSize / kPointerSize;
674 }
675
Ben Murdochb0fe1622011-05-05 13:52:32 +0100676 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100677 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100678 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100679 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100680 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
681 v->VisitPointer(parameters_base + reg_stack_index);
682 }
683 }
684 // Skip the words containing the register values.
685 parameters_base += kNumSafepointRegisters;
686 }
687
688 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100689 uint8_t* safepoint_bits = safepoint_entry.bits();
690 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100691
692 // Visit the rest of the parameters.
693 v->VisitPointers(parameters_base, parameters_limit);
694
695 // Visit pointer spill slots and locals.
696 for (unsigned index = 0; index < stack_slots; index++) {
697 int byte_index = index >> kBitsPerByteLog2;
698 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100699 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100700 v->VisitPointer(parameters_limit + index);
701 }
702 }
703
Ben Murdochb0fe1622011-05-05 13:52:32 +0100704 // Visit the return address in the callee and incoming arguments.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000705 IteratePc(v, pc_address(), constant_pool_address(), code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000706
707 // Visit the context in stub frame and JavaScript frame.
708 // Visit the function in JavaScript frame.
709 Object** fixed_base = &Memory::Object_at(
710 fp() + StandardFrameConstants::kMarkerOffset);
711 Object** fixed_limit = &Memory::Object_at(fp());
712 v->VisitPointers(fixed_base, fixed_limit);
713}
714
715
716void StubFrame::Iterate(ObjectVisitor* v) const {
717 IterateCompiledFrame(v);
718}
719
720
721Code* StubFrame::unchecked_code() const {
722 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
723}
724
725
726Address StubFrame::GetCallerStackPointer() const {
727 return fp() + ExitFrameConstants::kCallerSPDisplacement;
728}
729
730
731int StubFrame::GetNumberOfIncomingArguments() const {
732 return 0;
733}
734
735
736void OptimizedFrame::Iterate(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737 IterateCompiledFrame(v);
738}
739
740
741void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
742 Memory::Object_at(GetParameterSlot(index)) = value;
Steve Blocka7e24c12009-10-30 11:49:00 +0000743}
744
745
746bool JavaScriptFrame::IsConstructor() const {
747 Address fp = caller_fp();
748 if (has_adapted_arguments()) {
749 // Skip the arguments adaptor frame and look at the real caller.
750 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
751 }
752 return IsConstructFrame(fp);
753}
754
755
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000756bool JavaScriptFrame::HasInlinedFrames() const {
757 List<JSFunction*> functions(1);
758 GetFunctions(&functions);
759 return functions.length() > 1;
760}
761
762
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000763int JavaScriptFrame::GetArgumentsLength() const {
764 // If there is an arguments adaptor frame get the arguments length from it.
765 if (has_adapted_arguments()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100766 return ArgumentsAdaptorFrame::GetLength(caller_fp());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000767 } 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 Murdoch097c5b22016-05-18 11:27:45 +0100799 Code* code = LookupCode();
800 int offset = static_cast<int>(pc() - code->instruction_start());
801 AbstractCode* abstract_code = AbstractCode::cast(code);
802 FrameSummary summary(receiver(), function(), abstract_code, offset,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100803 IsConstructor());
804 functions->Add(summary);
805}
806
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807int JavaScriptFrame::LookupExceptionHandlerInTable(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100808 int* stack_depth, HandlerTable::CatchPrediction* prediction) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000809 Code* code = LookupCode();
810 DCHECK(!code->is_optimized_code());
811 HandlerTable* table = HandlerTable::cast(code->handler_table());
812 int pc_offset = static_cast<int>(pc() - code->entry());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100813 return table->LookupRange(pc_offset, stack_depth, prediction);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000814}
815
816
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
818 Address pc, FILE* file,
819 bool print_line_number) {
820 PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
821 function->PrintName(file);
822 int code_offset = static_cast<int>(pc - code->instruction_start());
823 PrintF(file, "+%d", code_offset);
824 if (print_line_number) {
825 SharedFunctionInfo* shared = function->shared();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100826 int source_pos = code->SourcePosition(code_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000827 Object* maybe_script = shared->script();
828 if (maybe_script->IsScript()) {
829 Script* script = Script::cast(maybe_script);
830 int line = script->GetLineNumber(source_pos) + 1;
831 Object* script_name_raw = script->name();
832 if (script_name_raw->IsString()) {
833 String* script_name = String::cast(script->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000834 base::SmartArrayPointer<char> c_script_name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
836 PrintF(file, " at %s:%d", c_script_name.get(), line);
837 } else {
838 PrintF(file, " at <unknown>:%d", line);
839 }
840 } else {
841 PrintF(file, " at <unknown>:<unknown>");
842 }
843 }
844}
845
846
847void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100848 bool print_line_number) {
849 // constructor calls
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000850 DisallowHeapAllocation no_allocation;
851 JavaScriptFrameIterator it(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100852 while (!it.done()) {
853 if (it.frame()->is_java_script()) {
854 JavaScriptFrame* frame = it.frame();
855 if (frame->IsConstructor()) PrintF(file, "new ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856 PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
857 frame->pc(), file, print_line_number);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100858 if (print_args) {
859 // function arguments
860 // (we are intentionally only printing the actually
861 // supplied parameters, not all parameters required)
862 PrintF(file, "(this=");
863 frame->receiver()->ShortPrint(file);
864 const int length = frame->ComputeParametersCount();
865 for (int i = 0; i < length; i++) {
866 PrintF(file, ", ");
867 frame->GetParameter(i)->ShortPrint(file);
868 }
869 PrintF(file, ")");
870 }
871 break;
872 }
873 it.Advance();
874 }
875}
876
877
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000878void JavaScriptFrame::SaveOperandStack(FixedArray* store) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879 int operands_count = store->length();
880 DCHECK_LE(operands_count, ComputeOperandsCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881 for (int i = 0; i < operands_count; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882 store->set(i, GetOperand(i));
883 }
884}
885
886
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000887void JavaScriptFrame::RestoreOperandStack(FixedArray* store) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888 int operands_count = store->length();
889 DCHECK_LE(operands_count, ComputeOperandsCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000890 for (int i = 0; i < operands_count; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
892 Memory::Object_at(GetOperandSlot(i)) = store->get(i);
893 }
894}
895
Ben Murdoch097c5b22016-05-18 11:27:45 +0100896FrameSummary::FrameSummary(Object* receiver, JSFunction* function,
897 AbstractCode* abstract_code, int code_offset,
898 bool is_constructor)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000899 : receiver_(receiver, function->GetIsolate()),
900 function_(function),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100901 abstract_code_(abstract_code),
902 code_offset_(code_offset),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000903 is_constructor_(is_constructor) {}
904
Ben Murdochb0fe1622011-05-05 13:52:32 +0100905void FrameSummary::Print() {
906 PrintF("receiver: ");
907 receiver_->ShortPrint();
908 PrintF("\nfunction: ");
909 function_->shared()->DebugName()->ShortPrint();
910 PrintF("\ncode: ");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100911 abstract_code_->ShortPrint();
912 if (abstract_code_->IsCode()) {
913 Code* code = abstract_code_->GetCode();
914 if (code->kind() == Code::FUNCTION) PrintF(" UNOPT ");
915 if (code->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT ");
916 } else {
917 PrintF(" BYTECODE ");
918 }
919 PrintF("\npc: %d\n", code_offset_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100920}
921
922
923void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000924 DCHECK(frames->length() == 0);
925 DCHECK(is_optimized());
926
927 // Delegate to JS frame in absence of turbofan deoptimization.
928 // TODO(turbofan): Revisit once we support deoptimization across the board.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929 if (LookupCode()->is_turbofanned() && function()->shared()->asm_function() &&
930 !FLAG_turbo_asm_deoptimization) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000931 return JavaScriptFrame::Summarize(frames);
932 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100933
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000934 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +0100935 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000936 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
937 FixedArray* const literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100938
939 TranslationIterator it(data->TranslationByteArray(),
940 data->TranslationIndex(deopt_index)->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000941 Translation::Opcode frame_opcode =
942 static_cast<Translation::Opcode>(it.Next());
943 DCHECK_EQ(Translation::BEGIN, frame_opcode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100944 it.Next(); // Drop frame count.
945 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100946
947 // We create the summary in reverse order because the frames
948 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100949 bool is_constructor = IsConstructor();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000950 while (jsframe_count != 0) {
951 frame_opcode = static_cast<Translation::Opcode>(it.Next());
952 if (frame_opcode == Translation::JS_FRAME ||
953 frame_opcode == Translation::INTERPRETED_FRAME) {
954 jsframe_count--;
955 BailoutId const ast_id = BailoutId(it.Next());
956 SharedFunctionInfo* const shared_info =
957 SharedFunctionInfo::cast(literal_array->get(it.Next()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100958 it.Next(); // Skip height.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 // The translation commands are ordered and the function is always
961 // at the first position, and the receiver is next.
962 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
963
964 // Get the correct function in the optimized frame.
965 JSFunction* function;
966 if (opcode == Translation::LITERAL) {
967 function = JSFunction::cast(literal_array->get(it.Next()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100969 CHECK_EQ(opcode, Translation::STACK_SLOT);
970 function = JSFunction::cast(StackSlotAt(it.Next()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000971 }
972 DCHECK_EQ(shared_info, function->shared());
973
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000974 // If we are at a call, the receiver is always in a stack slot.
975 // Otherwise we are not guaranteed to get the receiver value.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100976 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100977
978 // Get the correct receiver in the optimized frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000979 Object* receiver;
Ben Murdoch257744e2011-11-30 15:57:28 +0000980 if (opcode == Translation::LITERAL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981 receiver = literal_array->get(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000982 } else if (opcode == Translation::STACK_SLOT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000983 receiver = StackSlotAt(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000984 } else {
985 // The receiver is not in a stack slot nor in a literal. We give up.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000986 it.Skip(Translation::NumberOfOperandsFor(opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000987 // TODO(3029): Materializing a captured object (or duplicated
988 // object) is hard, we return undefined for now. This breaks the
989 // produced stack trace, as constructor frames aren't marked as
990 // such anymore.
991 receiver = isolate()->heap()->undefined_value();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100992 }
993
Ben Murdoch097c5b22016-05-18 11:27:45 +0100994 AbstractCode* abstract_code;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100995
Ben Murdoch097c5b22016-05-18 11:27:45 +0100996 unsigned code_offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 if (frame_opcode == Translation::JS_FRAME) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100998 Code* code = shared_info->code();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 DeoptimizationOutputData* const output_data =
1000 DeoptimizationOutputData::cast(code->deoptimization_data());
1001 unsigned const entry =
1002 Deoptimizer::GetOutputInfo(output_data, ast_id, shared_info);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001003 code_offset = FullCodeGenerator::PcField::decode(entry);
1004 abstract_code = AbstractCode::cast(code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 } else {
1006 // TODO(rmcilroy): Modify FrameSummary to enable us to summarize
1007 // based on the BytecodeArray and bytecode offset.
1008 DCHECK_EQ(frame_opcode, Translation::INTERPRETED_FRAME);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001009 code_offset = 0;
1010 abstract_code = AbstractCode::cast(shared_info->bytecode_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001012 FrameSummary summary(receiver, function, abstract_code, code_offset,
1013 is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001014 frames->Add(summary);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001015 is_constructor = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001016 } else if (frame_opcode == Translation::CONSTRUCT_STUB_FRAME) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001017 // The next encountered JS_FRAME will be marked as a constructor call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001018 it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001019 DCHECK(!is_constructor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001020 is_constructor = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001021 } else {
1022 // Skip over operands to advance to the next opcode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001023 it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001024 }
1025 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001026 DCHECK(!is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001027}
1028
1029
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001030int OptimizedFrame::LookupExceptionHandlerInTable(
1031 int* stack_slots, HandlerTable::CatchPrediction* prediction) {
1032 Code* code = LookupCode();
1033 DCHECK(code->is_optimized_code());
1034 HandlerTable* table = HandlerTable::cast(code->handler_table());
1035 int pc_offset = static_cast<int>(pc() - code->entry());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001036 if (stack_slots) *stack_slots = code->stack_slots();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001037 return table->LookupReturn(pc_offset, prediction);
1038}
1039
1040
Ben Murdochb0fe1622011-05-05 13:52:32 +01001041DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001042 int* deopt_index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001043 DCHECK(is_optimized());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001044
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001045 JSFunction* opt_function = function();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001046 Code* code = opt_function->code();
1047
1048 // The code object may have been replaced by lazy deoptimization. Fall
1049 // back to a slow search in this case to find the original optimized
1050 // code object.
1051 if (!code->contains(pc())) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001052 code = isolate()->inner_pointer_to_code_cache()->
1053 GcSafeFindCodeForInnerPointer(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001054 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001055 DCHECK(code != NULL);
1056 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001057
Ben Murdochb8e0da22011-05-16 14:20:40 +01001058 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1059 *deopt_index = safepoint_entry.deoptimization_index();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001060 DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001061
1062 return DeoptimizationInputData::cast(code->deoptimization_data());
1063}
1064
1065
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001066void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001067 DCHECK(functions->length() == 0);
1068 DCHECK(is_optimized());
1069
1070 // Delegate to JS frame in absence of turbofan deoptimization.
1071 // TODO(turbofan): Revisit once we support deoptimization across the board.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 if (LookupCode()->is_turbofanned() && function()->shared()->asm_function() &&
1073 !FLAG_turbo_asm_deoptimization) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001074 return JavaScriptFrame::GetFunctions(functions);
1075 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001076
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001077 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +01001078 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001079 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
1080 FixedArray* const literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001081
1082 TranslationIterator it(data->TranslationByteArray(),
1083 data->TranslationIndex(deopt_index)->value());
1084 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001085 DCHECK_EQ(Translation::BEGIN, opcode);
1086 it.Next(); // Skip frame count.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001087 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001088
1089 // We insert the frames in reverse order because the frames
1090 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001091 while (jsframe_count != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001092 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001093 // Skip over operands to advance to the next opcode.
1094 it.Skip(Translation::NumberOfOperandsFor(opcode));
1095 if (opcode == Translation::JS_FRAME ||
1096 opcode == Translation::INTERPRETED_FRAME) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001097 jsframe_count--;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001098
1099 // The translation commands are ordered and the function is always at the
1100 // first position.
1101 opcode = static_cast<Translation::Opcode>(it.Next());
1102
1103 // Get the correct function in the optimized frame.
1104 Object* function;
1105 if (opcode == Translation::LITERAL) {
1106 function = literal_array->get(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001107 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001108 CHECK_EQ(Translation::STACK_SLOT, opcode);
1109 function = StackSlotAt(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001110 }
1111 functions->Add(JSFunction::cast(function));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001112 }
1113 }
1114}
1115
1116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001117int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) {
1118 return StandardFrameConstants::kCallerSPOffset -
1119 ((slot_index + 1) * kPointerSize);
1120}
1121
1122
1123Object* OptimizedFrame::StackSlotAt(int index) const {
1124 return Memory::Object_at(fp() + StackSlotOffsetRelativeToFp(index));
1125}
1126
Ben Murdoch097c5b22016-05-18 11:27:45 +01001127int InterpretedFrame::LookupExceptionHandlerInTable(
1128 int* context_register, HandlerTable::CatchPrediction* prediction) {
1129 BytecodeArray* bytecode = function()->shared()->bytecode_array();
1130 HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
1131 int pc_offset = GetBytecodeOffset() + 1; // Point after current bytecode.
1132 return table->LookupRange(pc_offset, context_register, prediction);
1133}
1134
1135int InterpretedFrame::GetBytecodeOffset() const {
1136 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1137 DCHECK_EQ(
1138 InterpreterFrameConstants::kBytecodeOffsetFromFp,
1139 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1140 int raw_offset = Smi::cast(GetExpression(index))->value();
1141 return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
1142}
1143
1144void InterpretedFrame::PatchBytecodeOffset(int new_offset) {
1145 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1146 DCHECK_EQ(
1147 InterpreterFrameConstants::kBytecodeOffsetFromFp,
1148 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1149 int raw_offset = new_offset + BytecodeArray::kHeaderSize - kHeapObjectTag;
1150 SetExpression(index, Smi::FromInt(raw_offset));
1151}
1152
1153Object* InterpretedFrame::GetBytecodeArray() const {
1154 const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1155 DCHECK_EQ(
1156 InterpreterFrameConstants::kBytecodeArrayFromFp,
1157 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1158 return GetExpression(index);
1159}
1160
1161void InterpretedFrame::PatchBytecodeArray(Object* bytecode_array) {
1162 const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1163 DCHECK_EQ(
1164 InterpreterFrameConstants::kBytecodeArrayFromFp,
1165 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1166 SetExpression(index, bytecode_array);
1167}
1168
1169Object* InterpretedFrame::GetInterpreterRegister(int register_index) const {
1170 const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1171 DCHECK_EQ(
1172 InterpreterFrameConstants::kRegisterFilePointerFromFp,
1173 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1174 return GetExpression(index + register_index);
1175}
1176
1177void InterpretedFrame::Summarize(List<FrameSummary>* functions) {
1178 DCHECK(functions->length() == 0);
1179 AbstractCode* abstract_code =
1180 AbstractCode::cast(function()->shared()->bytecode_array());
1181 FrameSummary summary(receiver(), function(), abstract_code,
1182 GetBytecodeOffset(), IsConstructor());
1183 functions->Add(summary);
1184}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001186int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
1187 return Smi::cast(GetExpression(0))->value();
1188}
1189
1190
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001191Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001192 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001193}
1194
Ben Murdoch097c5b22016-05-18 11:27:45 +01001195int ArgumentsAdaptorFrame::GetLength(Address fp) {
1196 const int offset = ArgumentsAdaptorFrameConstants::kLengthOffset;
1197 return Smi::cast(Memory::Object_at(fp + offset))->value();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001198}
1199
Iain Merrick75681382010-08-19 15:07:18 +01001200Code* ArgumentsAdaptorFrame::unchecked_code() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001201 return isolate()->builtins()->builtin(
Steve Block44f0eee2011-05-26 01:26:41 +01001202 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +00001203}
1204
Ben Murdoch097c5b22016-05-18 11:27:45 +01001205Address InternalFrame::GetCallerStackPointer() const {
1206 // Internal frames have no arguments. The stack pointer of the
1207 // caller is at a fixed offset from the frame pointer.
1208 return fp() + StandardFrameConstants::kCallerSPOffset;
1209}
Steve Blocka7e24c12009-10-30 11:49:00 +00001210
Iain Merrick75681382010-08-19 15:07:18 +01001211Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001212 const int offset = InternalFrameConstants::kCodeOffset;
1213 Object* code = Memory::Object_at(fp() + offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214 DCHECK(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +01001215 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001216}
1217
1218
1219void StackFrame::PrintIndex(StringStream* accumulator,
1220 PrintMode mode,
1221 int index) {
1222 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1223}
1224
1225
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226namespace {
1227
1228
1229void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared,
1230 Code* code) {
1231 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1232 std::ostringstream os;
1233 os << "--------- s o u r c e c o d e ---------\n"
1234 << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1235 << "\n-----------------------------------------\n";
1236 accumulator->Add(os.str().c_str());
1237 }
1238}
1239
1240
1241} // namespace
1242
1243
Steve Blocka7e24c12009-10-30 11:49:00 +00001244void JavaScriptFrame::Print(StringStream* accumulator,
1245 PrintMode mode,
1246 int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001247 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001248 Object* receiver = this->receiver();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001249 JSFunction* function = this->function();
Steve Blocka7e24c12009-10-30 11:49:00 +00001250
1251 accumulator->PrintSecurityTokenIfChanged(function);
1252 PrintIndex(accumulator, mode, index);
1253 Code* code = NULL;
1254 if (IsConstructor()) accumulator->Add("new ");
1255 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +01001256
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001257 // Get scope information for nicer output, if possible. If code is NULL, or
1258 // doesn't contain scope info, scope_info will return 0 for the number of
1259 // parameters, stack local variables, context local variables, stack slots,
1260 // or context slots.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001261 SharedFunctionInfo* shared = function->shared();
1262 ScopeInfo* scope_info = shared->scope_info();
1263 Object* script_obj = shared->script();
1264 if (script_obj->IsScript()) {
1265 Script* script = Script::cast(script_obj);
1266 accumulator->Add(" [");
1267 accumulator->PrintName(script->name());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001268
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001269 Address pc = this->pc();
1270 if (code != NULL && code->kind() == Code::FUNCTION &&
1271 pc >= code->instruction_start() && pc < code->instruction_end()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001272 int offset = static_cast<int>(pc - code->instruction_start());
1273 int source_pos = code->SourcePosition(offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001274 int line = script->GetLineNumber(source_pos) + 1;
1275 accumulator->Add(":%d", line);
1276 } else {
1277 int function_start_pos = shared->start_position();
1278 int line = script->GetLineNumber(function_start_pos) + 1;
1279 accumulator->Add(":~%d", line);
Steve Block6ded16b2010-05-10 14:33:55 +01001280 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001281
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001282 accumulator->Add("] [pc=%p] ", pc);
Steve Block6ded16b2010-05-10 14:33:55 +01001283 }
1284
Steve Blocka7e24c12009-10-30 11:49:00 +00001285 accumulator->Add("(this=%o", receiver);
1286
Steve Blocka7e24c12009-10-30 11:49:00 +00001287 // Print the parameters.
1288 int parameters_count = ComputeParametersCount();
1289 for (int i = 0; i < parameters_count; i++) {
1290 accumulator->Add(",");
1291 // If we have a name for the parameter we print it. Nameless
1292 // parameters are either because we have more actual parameters
1293 // than formal parameters or because we have no scope information.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001294 if (i < scope_info->ParameterCount()) {
1295 accumulator->PrintName(scope_info->ParameterName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001296 accumulator->Add("=");
1297 }
1298 accumulator->Add("%o", GetParameter(i));
1299 }
1300
1301 accumulator->Add(")");
1302 if (mode == OVERVIEW) {
1303 accumulator->Add("\n");
1304 return;
1305 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001306 if (is_optimized()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001307 accumulator->Add(" {\n// optimized frame\n");
1308 PrintFunctionSource(accumulator, shared, code);
1309 accumulator->Add("}\n");
Ben Murdoch257744e2011-11-30 15:57:28 +00001310 return;
1311 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001312 accumulator->Add(" {\n");
1313
1314 // Compute the number of locals and expression stack elements.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001315 int stack_locals_count = scope_info->StackLocalCount();
1316 int heap_locals_count = scope_info->ContextLocalCount();
Steve Blocka7e24c12009-10-30 11:49:00 +00001317 int expressions_count = ComputeExpressionsCount();
1318
1319 // Print stack-allocated local variables.
1320 if (stack_locals_count > 0) {
1321 accumulator->Add(" // stack-allocated locals\n");
1322 }
1323 for (int i = 0; i < stack_locals_count; i++) {
1324 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001325 accumulator->PrintName(scope_info->StackLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001326 accumulator->Add(" = ");
1327 if (i < expressions_count) {
1328 accumulator->Add("%o", GetExpression(i));
1329 } else {
1330 accumulator->Add("// no expression found - inconsistent frame?");
1331 }
1332 accumulator->Add("\n");
1333 }
1334
1335 // Try to get hold of the context of this frame.
1336 Context* context = NULL;
1337 if (this->context() != NULL && this->context()->IsContext()) {
1338 context = Context::cast(this->context());
1339 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001340 while (context->IsWithContext()) {
1341 context = context->previous();
1342 DCHECK(context != NULL);
1343 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001344
1345 // Print heap-allocated local variables.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001346 if (heap_locals_count > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001347 accumulator->Add(" // heap-allocated locals\n");
1348 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001349 for (int i = 0; i < heap_locals_count; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001350 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001351 accumulator->PrintName(scope_info->ContextLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001352 accumulator->Add(" = ");
1353 if (context != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001354 int index = Context::MIN_CONTEXT_SLOTS + i;
1355 if (index < context->length()) {
1356 accumulator->Add("%o", context->get(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00001357 } else {
1358 accumulator->Add(
1359 "// warning: missing context slot - inconsistent frame?");
1360 }
1361 } else {
1362 accumulator->Add("// warning: no context found - inconsistent frame?");
1363 }
1364 accumulator->Add("\n");
1365 }
1366
1367 // Print the expression stack.
1368 int expressions_start = stack_locals_count;
1369 if (expressions_start < expressions_count) {
1370 accumulator->Add(" // expression stack (top to bottom)\n");
1371 }
1372 for (int i = expressions_count - 1; i >= expressions_start; i--) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001373 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1374 }
1375
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001376 PrintFunctionSource(accumulator, shared, code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001377
1378 accumulator->Add("}\n\n");
1379}
1380
1381
1382void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1383 PrintMode mode,
1384 int index) const {
1385 int actual = ComputeParametersCount();
1386 int expected = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 JSFunction* function = this->function();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001388 expected = function->shared()->internal_formal_parameter_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00001389
1390 PrintIndex(accumulator, mode, index);
1391 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1392 if (mode == OVERVIEW) {
1393 accumulator->Add("\n");
1394 return;
1395 }
1396 accumulator->Add(" {\n");
1397
1398 // Print actual arguments.
1399 if (actual > 0) accumulator->Add(" // actual arguments\n");
1400 for (int i = 0; i < actual; i++) {
1401 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1402 if (expected != -1 && i >= expected) {
1403 accumulator->Add(" // not passed to callee");
1404 }
1405 accumulator->Add("\n");
1406 }
1407
1408 accumulator->Add("}\n\n");
1409}
1410
1411
1412void EntryFrame::Iterate(ObjectVisitor* v) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001413 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001414}
1415
1416
1417void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001418 const int offset = StandardFrameConstants::kLastObjectOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +00001419 Object** base = &Memory::Object_at(sp());
1420 Object** limit = &Memory::Object_at(fp() + offset) + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00001421 v->VisitPointers(base, limit);
1422}
1423
1424
1425void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1426 IterateExpressions(v);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001427 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001428}
1429
Steve Blocka7e24c12009-10-30 11:49:00 +00001430void InternalFrame::Iterate(ObjectVisitor* v) const {
1431 // Internal frames only have object pointers on the expression stack
1432 // as they never have any arguments.
1433 IterateExpressions(v);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001434 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001435}
1436
1437
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001438void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
1439 Object** base = &Memory::Object_at(sp());
1440 Object** limit = &Memory::Object_at(fp() +
1441 kFirstRegisterParameterFrameOffset);
1442 v->VisitPointers(base, limit);
1443 base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset);
1444 const int offset = StandardFrameConstants::kLastObjectOffset;
1445 limit = &Memory::Object_at(fp() + offset) + 1;
1446 v->VisitPointers(base, limit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001447 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001448}
1449
1450
1451Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
1452 return fp() + StandardFrameConstants::kCallerSPOffset;
1453}
1454
1455
1456Code* StubFailureTrampolineFrame::unchecked_code() const {
1457 Code* trampoline;
1458 StubFailureTrampolineStub(isolate(), NOT_JS_FUNCTION_STUB_MODE).
1459 FindCodeInCache(&trampoline);
1460 if (trampoline->contains(pc())) {
1461 return trampoline;
1462 }
1463
1464 StubFailureTrampolineStub(isolate(), JS_FUNCTION_STUB_MODE).
1465 FindCodeInCache(&trampoline);
1466 if (trampoline->contains(pc())) {
1467 return trampoline;
1468 }
1469
1470 UNREACHABLE();
1471 return NULL;
1472}
1473
1474
Steve Blocka7e24c12009-10-30 11:49:00 +00001475// -------------------------------------------------------------------------
1476
1477
1478JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001479 DCHECK(n >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001480 for (int i = 0; i <= n; i++) {
1481 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1482 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1483 iterator_.Advance();
1484 }
1485 UNREACHABLE();
1486 return NULL;
1487}
1488
1489
1490// -------------------------------------------------------------------------
1491
1492
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001493static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1494 MapWord map_word = object->map_word();
1495 return map_word.IsForwardingAddress() ?
1496 map_word.ToForwardingAddress()->map() : map_word.ToMap();
1497}
1498
1499
1500static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1501 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1502}
1503
1504
1505#ifdef DEBUG
1506static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1507 Map* map = GcSafeMapOfCodeSpaceObject(code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001508 DCHECK(map == code->GetHeap()->code_map());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001509 Address start = code->address();
1510 Address end = code->address() + code->SizeFromMap(map);
1511 return start <= addr && addr < end;
1512}
1513#endif
1514
1515
1516Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1517 Address inner_pointer) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001518 Code* code = reinterpret_cast<Code*>(object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001519 DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001520 return code;
1521}
1522
1523
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001524Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1525 Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001526 Heap* heap = isolate_->heap();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001527
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001528 // Check if the inner pointer points into a large object chunk.
1529 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1530 if (large_page != NULL) {
1531 return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1532 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001533
Ben Murdoch097c5b22016-05-18 11:27:45 +01001534 if (!heap->code_space()->Contains(inner_pointer)) {
1535 return nullptr;
1536 }
1537
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001538 // Iterate through the page until we reach the end or find an object starting
1539 // after the inner pointer.
1540 Page* page = Page::FromAddress(inner_pointer);
1541
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001542 DCHECK_EQ(page->owner(), heap->code_space());
1543 heap->mark_compact_collector()->SweepOrWaitUntilSweepingCompleted(page);
1544
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001545 Address addr = page->skip_list()->StartFor(inner_pointer);
1546
1547 Address top = heap->code_space()->top();
1548 Address limit = heap->code_space()->limit();
1549
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001550 while (true) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001551 if (addr == top && addr != limit) {
1552 addr = limit;
1553 continue;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001554 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001555
1556 HeapObject* obj = HeapObject::FromAddress(addr);
1557 int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1558 Address next_addr = addr + obj_size;
1559 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1560 addr = next_addr;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001561 }
1562}
1563
Ben Murdochb0fe1622011-05-05 13:52:32 +01001564
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001565InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1566 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001567 isolate_->counters()->pc_to_code()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001568 DCHECK(base::bits::IsPowerOfTwo32(kInnerPointerToCodeCacheSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001569 uint32_t hash = ComputeIntegerHash(ObjectAddressForHashing(inner_pointer),
1570 v8::internal::kZeroHashSeed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001571 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1572 InnerPointerToCodeCacheEntry* entry = cache(index);
1573 if (entry->inner_pointer == inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001574 isolate_->counters()->pc_to_code_cached()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001575 DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001576 } else {
1577 // Because this code may be interrupted by a profiling signal that
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001578 // also queries the cache, we cannot update inner_pointer before the code
1579 // has been set. Otherwise, we risk trying to use a cache entry before
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001580 // the code has been computed.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001581 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001582 entry->safepoint_entry.Reset();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001583 entry->inner_pointer = inner_pointer;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001584 }
1585 return entry;
1586}
1587
1588
1589// -------------------------------------------------------------------------
1590
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001591
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001592int NumRegs(RegList reglist) { return base::bits::CountPopulation(reglist); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001593
1594
1595struct JSCallerSavedCodeData {
Steve Block44f0eee2011-05-26 01:26:41 +01001596 int reg_code[kNumJSCallerSaved];
1597};
1598
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001599JSCallerSavedCodeData caller_saved_code_data;
Steve Block44f0eee2011-05-26 01:26:41 +01001600
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001601void SetUpJSCallerSavedCodeData() {
1602 int i = 0;
1603 for (int r = 0; r < kNumRegs; r++)
1604 if ((kJSCallerSaved & (1 << r)) != 0)
1605 caller_saved_code_data.reg_code[i++] = r;
1606
1607 DCHECK(i == kNumJSCallerSaved);
1608}
1609
Steve Block44f0eee2011-05-26 01:26:41 +01001610
1611int JSCallerSavedCode(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001612 DCHECK(0 <= n && n < kNumJSCallerSaved);
1613 return caller_saved_code_data.reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001614}
1615
1616
Steve Block6ded16b2010-05-10 14:33:55 +01001617#define DEFINE_WRAPPER(type, field) \
1618class field##_Wrapper : public ZoneObject { \
1619 public: /* NOLINT */ \
1620 field##_Wrapper(const field& original) : frame_(original) { \
1621 } \
1622 field frame_; \
1623};
1624STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1625#undef DEFINE_WRAPPER
1626
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001627static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
Steve Block6ded16b2010-05-10 14:33:55 +01001628#define FRAME_TYPE_CASE(type, field) \
1629 case StackFrame::type: { \
1630 field##_Wrapper* wrapper = \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001631 new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
Steve Block6ded16b2010-05-10 14:33:55 +01001632 return &wrapper->frame_; \
1633 }
1634
1635 switch (frame->type()) {
1636 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1637 default: UNREACHABLE();
1638 }
1639#undef FRAME_TYPE_CASE
1640 return NULL;
1641}
1642
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001643
1644Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
1645 ZoneList<StackFrame*> list(10, zone);
1646 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1647 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1648 list.Add(frame, zone);
Steve Block6ded16b2010-05-10 14:33:55 +01001649 }
1650 return list.ToVector();
1651}
1652
1653
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001654} // namespace internal
1655} // namespace v8