blob: 0e57429ea3077e2f50e056369ff6406b0ed34b70 [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
Steve Blocka7e24c12009-10-30 11:49:00 +0000137// -------------------------------------------------------------------------
138
Ben Murdochda12d292016-06-02 14:46:10 +0100139JavaScriptFrameIterator::JavaScriptFrameIterator(Isolate* isolate,
140 StackFrame::Id id)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141 : iterator_(isolate) {
142 while (!done()) {
143 Advance();
144 if (frame()->id() == id) return;
145 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000146}
147
148
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149void JavaScriptFrameIterator::Advance() {
150 do {
151 iterator_.Advance();
152 } while (!iterator_.done() && !iterator_.frame()->is_java_script());
153}
154
155
156void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
157 if (!frame()->has_adapted_arguments()) return;
158 iterator_.Advance();
159 DCHECK(iterator_.frame()->is_arguments_adaptor());
160}
161
162
163// -------------------------------------------------------------------------
164
165
Ben Murdoch8b112d22011-06-08 16:22:53 +0100166StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
167 : JavaScriptFrameIterator(isolate) {
168 if (!done() && !IsValidFrame()) Advance();
169}
170
171
Steve Blocka7e24c12009-10-30 11:49:00 +0000172void StackTraceFrameIterator::Advance() {
173 while (true) {
174 JavaScriptFrameIterator::Advance();
175 if (done()) return;
Leon Clarke4515c472010-02-03 11:58:03 +0000176 if (IsValidFrame()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000177 }
178}
179
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180
Leon Clarke4515c472010-02-03 11:58:03 +0000181bool StackTraceFrameIterator::IsValidFrame() {
182 if (!frame()->function()->IsJSFunction()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 Object* script = frame()->function()->shared()->script();
Leon Clarke4515c472010-02-03 11:58:03 +0000184 // Don't show functions from native scripts to user.
185 return (script->IsScript() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 Script::TYPE_NATIVE != Script::cast(script)->type());
Leon Clarke4515c472010-02-03 11:58:03 +0000187}
188
Steve Blocka7e24c12009-10-30 11:49:00 +0000189
190// -------------------------------------------------------------------------
191
192
193SafeStackFrameIterator::SafeStackFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100194 Isolate* isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195 Address fp, Address sp, Address js_entry_sp)
196 : StackFrameIteratorBase(isolate, false),
197 low_bound_(sp),
198 high_bound_(js_entry_sp),
199 top_frame_type_(StackFrame::NONE),
200 external_callback_scope_(isolate->external_callback_scope()) {
201 StackFrame::State state;
202 StackFrame::Type type;
Steve Block44f0eee2011-05-26 01:26:41 +0100203 ThreadLocalTop* top = isolate->thread_local_top();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 if (IsValidTop(top)) {
205 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
206 top_frame_type_ = type;
207 } else if (IsValidStackAddress(fp)) {
208 DCHECK(fp != NULL);
209 state.fp = fp;
210 state.sp = sp;
211 state.pc_address = StackFrame::ResolveReturnAddressLocation(
212 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
213 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
214 // we check only that kMarkerOffset is within the stack bounds and do
215 // compile time check that kContextOffset slot is pushed on the stack before
216 // kMarkerOffset.
Ben Murdochda12d292016-06-02 14:46:10 +0100217 STATIC_ASSERT(StandardFrameConstants::kFunctionOffset <
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 StandardFrameConstants::kContextOffset);
Ben Murdochda12d292016-06-02 14:46:10 +0100219 Address frame_marker = fp + StandardFrameConstants::kFunctionOffset;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220 if (IsValidStackAddress(frame_marker)) {
221 type = StackFrame::ComputeType(this, &state);
222 top_frame_type_ = type;
223 } else {
224 // Mark the frame as JAVA_SCRIPT if we cannot determine its type.
225 // The frame anyways will be skipped.
226 type = StackFrame::JAVA_SCRIPT;
227 // Top frame is incomplete so we cannot reliably determine its type.
228 top_frame_type_ = StackFrame::NONE;
229 }
230 } else {
231 return;
232 }
233 if (SingletonFor(type) == NULL) return;
234 frame_ = SingletonFor(type, &state);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100235 DCHECK(frame_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 Advance();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100237}
238
239
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
241 Address c_entry_fp = Isolate::c_entry_fp(top);
242 if (!IsValidExitFrame(c_entry_fp)) return false;
243 // There should be at least one JS_ENTRY stack handler.
244 Address handler = Isolate::handler(top);
245 if (handler == NULL) return false;
246 // Check that there are no js frames on top of the native frames.
247 return c_entry_fp < handler;
248}
249
250
251void SafeStackFrameIterator::AdvanceOneFrame() {
252 DCHECK(!done());
253 StackFrame* last_frame = frame_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000254 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 // Before advancing to the next stack frame, perform pointer validity tests.
256 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
257 frame_ = NULL;
258 return;
259 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000260
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261 // Advance to the previous frame.
262 StackFrame::State state;
263 StackFrame::Type type = frame_->GetCallerState(&state);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100264 if (SingletonFor(type) == NULL) {
265 frame_ = NULL;
266 return;
267 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268 frame_ = SingletonFor(type, &state);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100269 DCHECK(frame_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000270
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 // Check that we have actually moved to the previous frame in the stack.
272 if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
273 frame_ = NULL;
274 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000275}
276
277
278bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
279 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
280}
281
282
283bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
284 StackFrame::State state;
285 if (frame->is_entry() || frame->is_entry_construct()) {
286 // See EntryFrame::GetCallerState. It computes the caller FP address
287 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
288 // sure that caller FP address is valid.
289 Address caller_fp = Memory::Address_at(
290 frame->fp() + EntryFrameConstants::kCallerFPOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 if (!IsValidExitFrame(caller_fp)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000292 } else if (frame->is_arguments_adaptor()) {
293 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
294 // the number of arguments is stored on stack as Smi. We need to check
295 // that it really an Smi.
296 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
297 GetExpression(0);
298 if (!number_of_args->IsSmi()) {
299 return false;
300 }
301 }
302 frame->ComputeCallerState(&state);
303 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000304 SingletonFor(frame->GetCallerState(&state)) != NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000305}
306
307
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
309 if (!IsValidStackAddress(fp)) return false;
310 Address sp = ExitFrame::ComputeStackPointer(fp);
311 if (!IsValidStackAddress(sp)) return false;
312 StackFrame::State state;
313 ExitFrame::FillState(fp, sp, &state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000314 return *state.pc_address != NULL;
315}
316
317
318void SafeStackFrameIterator::Advance() {
319 while (true) {
320 AdvanceOneFrame();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100321 if (done()) break;
322 ExternalCallbackScope* last_callback_scope = NULL;
323 while (external_callback_scope_ != NULL &&
324 external_callback_scope_->scope_address() < frame_->fp()) {
325 // As long as the setup of a frame is not atomic, we may happen to be
326 // in an interval where an ExternalCallbackScope is already created,
327 // but the frame is not yet entered. So we are actually observing
328 // the previous frame.
329 // Skip all the ExternalCallbackScope's that are below the current fp.
330 last_callback_scope = external_callback_scope_;
331 external_callback_scope_ = external_callback_scope_->previous();
332 }
333 if (frame_->is_java_script()) break;
334 if (frame_->is_exit()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335 // Some of the EXIT frames may have ExternalCallbackScope allocated on
336 // top of them. In that case the scope corresponds to the first EXIT
337 // frame beneath it. There may be other EXIT frames on top of the
338 // ExternalCallbackScope, just skip them as we cannot collect any useful
339 // information about them.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100340 if (last_callback_scope) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 frame_->state_.pc_address =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100342 last_callback_scope->callback_entrypoint_address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000343 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100344 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000346 }
347}
348
349
350// -------------------------------------------------------------------------
351
352
Ben Murdoch8b112d22011-06-08 16:22:53 +0100353Code* StackFrame::GetSafepointData(Isolate* isolate,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100354 Address inner_pointer,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100355 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100356 unsigned* stack_slots) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100357 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
358 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100359 if (!entry->safepoint_entry.is_valid()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100360 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 DCHECK(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100362 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 DCHECK(entry->safepoint_entry.Equals(
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100364 entry->code->GetSafepointEntry(inner_pointer)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100365 }
366
367 // Fill in the results and return the code.
368 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100369 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100370 *stack_slots = code->stack_slots();
371 return code;
372}
373
374
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100375#ifdef DEBUG
376static bool GcSafeCodeContains(HeapObject* object, Address addr);
377#endif
378
379
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000380void StackFrame::IteratePc(ObjectVisitor* v, Address* pc_address,
381 Address* constant_pool_address, Code* holder) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100382 Address pc = *pc_address;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000383 DCHECK(GcSafeCodeContains(holder, pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100384 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
385 Object* code = holder;
386 v->VisitPointer(&code);
387 if (code != holder) {
388 holder = reinterpret_cast<Code*>(code);
389 pc = holder->instruction_start() + pc_offset;
390 *pc_address = pc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000391 if (FLAG_enable_embedded_constant_pool && constant_pool_address) {
392 *constant_pool_address = holder->constant_pool();
393 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000394 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000395}
396
397
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100398void StackFrame::SetReturnAddressLocationResolver(
399 ReturnAddressLocationResolver resolver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000400 DCHECK(return_address_location_resolver_ == NULL);
401 return_address_location_resolver_ = resolver;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100402}
403
Ben Murdochda12d292016-06-02 14:46:10 +0100404static bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
405 Code* interpreter_entry_trampoline =
406 isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
407 Code* interpreter_bytecode_dispatch =
408 isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
409
410 return (pc >= interpreter_entry_trampoline->instruction_start() &&
411 pc < interpreter_entry_trampoline->instruction_end()) ||
412 (pc >= interpreter_bytecode_dispatch->instruction_start() &&
413 pc < interpreter_bytecode_dispatch->instruction_end());
414}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100415
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000416StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
417 State* state) {
418 DCHECK(state->fp != NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419
Ben Murdochda12d292016-06-02 14:46:10 +0100420#if defined(USE_SIMULATOR)
421 MSAN_MEMORY_IS_INITIALIZED(
422 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset,
423 kPointerSize);
424#endif
425 Object* marker = Memory::Object_at(
426 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000427 if (!iterator->can_access_heap_objects_) {
428 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really
429 // means that we are being called from the profiler, which can interrupt
430 // the VM with a signal at any arbitrary instruction, with essentially
431 // anything on the stack. So basically none of these checks are 100%
432 // reliable.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100433#if defined(USE_SIMULATOR)
434 MSAN_MEMORY_IS_INITIALIZED(
Ben Murdochda12d292016-06-02 14:46:10 +0100435 state->fp + StandardFrameConstants::kFunctionOffset, kPointerSize);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100436#endif
Ben Murdochda12d292016-06-02 14:46:10 +0100437 Object* maybe_function =
438 Memory::Object_at(state->fp + StandardFrameConstants::kFunctionOffset);
439 if (!marker->IsSmi()) {
440 if (maybe_function->IsSmi()) {
441 return NONE;
442 } else if (FLAG_ignition && IsInterpreterFramePc(iterator->isolate(),
443 *(state->pc_address))) {
444 return INTERPRETED;
445 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 return JAVA_SCRIPT;
Ben Murdochda12d292016-06-02 14:46:10 +0100447 }
448 }
449 } else {
450 // Look up the code object to figure out the type of the stack frame.
451 Code* code_obj =
452 GetContainingCode(iterator->isolate(), *(state->pc_address));
453 if (code_obj != nullptr) {
454 if (code_obj->is_interpreter_entry_trampoline() ||
455 code_obj->is_interpreter_enter_bytecode_dispatch()) {
456 return INTERPRETED;
457 }
458 switch (code_obj->kind()) {
459 case Code::BUILTIN:
460 if (marker->IsSmi()) break;
461 // We treat frames for BUILTIN Code objects as OptimizedFrame for now
462 // (all the builtins with JavaScript linkage are actually generated
463 // with TurboFan currently, so this is sound).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464 return OPTIMIZED;
Ben Murdochda12d292016-06-02 14:46:10 +0100465 case Code::FUNCTION:
466 return JAVA_SCRIPT;
467 case Code::OPTIMIZED_FUNCTION:
468 return OPTIMIZED;
469 case Code::WASM_FUNCTION:
470 return WASM;
471 case Code::WASM_TO_JS_FUNCTION:
472 return WASM_TO_JS;
473 case Code::JS_TO_WASM_FUNCTION:
474 return JS_TO_WASM;
475 default:
476 // All other types should have an explicit marker
477 break;
478 }
479 } else {
480 return NONE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000481 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100482 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483
Ben Murdochda12d292016-06-02 14:46:10 +0100484 DCHECK(marker->IsSmi());
485 StackFrame::Type candidate =
486 static_cast<StackFrame::Type>(Smi::cast(marker)->value());
487 switch (candidate) {
488 case ENTRY:
489 case ENTRY_CONSTRUCT:
490 case EXIT:
491 case STUB:
492 case STUB_FAILURE_TRAMPOLINE:
493 case INTERNAL:
494 case CONSTRUCT:
495 case ARGUMENTS_ADAPTOR:
496 return candidate;
497 case JS_TO_WASM:
498 case WASM_TO_JS:
499 case WASM:
500 case JAVA_SCRIPT:
501 case OPTIMIZED:
502 case INTERPRETED:
503 default:
504 // Unoptimized and optimized JavaScript frames, including
505 // interpreted frames, should never have a StackFrame::Type
506 // marker. If we find one, we're likely being called from the
507 // profiler in a bogus stack frame.
508 return NONE;
509 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000510}
511
512
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000513#ifdef DEBUG
514bool StackFrame::can_access_heap_objects() const {
515 return iterator_->can_access_heap_objects_;
516}
517#endif
518
Steve Blocka7e24c12009-10-30 11:49:00 +0000519
520StackFrame::Type StackFrame::GetCallerState(State* state) const {
521 ComputeCallerState(state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522 return ComputeType(iterator_, state);
523}
524
525
526Address StackFrame::UnpaddedFP() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000527 return fp();
Steve Blocka7e24c12009-10-30 11:49:00 +0000528}
529
530
Iain Merrick75681382010-08-19 15:07:18 +0100531Code* EntryFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 return isolate()->heap()->js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000533}
534
535
536void EntryFrame::ComputeCallerState(State* state) const {
537 GetCallerState(state);
538}
539
540
Steve Block6ded16b2010-05-10 14:33:55 +0100541void EntryFrame::SetCallerFp(Address caller_fp) {
542 const int offset = EntryFrameConstants::kCallerFPOffset;
543 Memory::Address_at(this->fp() + offset) = caller_fp;
544}
545
546
Steve Blocka7e24c12009-10-30 11:49:00 +0000547StackFrame::Type EntryFrame::GetCallerState(State* state) const {
548 const int offset = EntryFrameConstants::kCallerFPOffset;
549 Address fp = Memory::Address_at(this->fp() + offset);
550 return ExitFrame::GetStateForFramePointer(fp, state);
551}
552
553
Iain Merrick75681382010-08-19 15:07:18 +0100554Code* EntryConstructFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 return isolate()->heap()->js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000556}
557
558
Steve Blockd0582a62009-12-15 09:54:21 +0000559Object*& ExitFrame::code_slot() const {
560 const int offset = ExitFrameConstants::kCodeOffset;
561 return Memory::Object_at(fp() + offset);
562}
563
564
Iain Merrick75681382010-08-19 15:07:18 +0100565Code* ExitFrame::unchecked_code() const {
566 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000567}
568
569
570void ExitFrame::ComputeCallerState(State* state) const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100571 // Set up the caller state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000572 state->sp = caller_sp();
573 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100574 state->pc_address = ResolveReturnAddressLocation(
575 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000577 state->constant_pool_address = reinterpret_cast<Address*>(
578 fp() + ExitFrameConstants::kConstantPoolOffset);
579 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000580}
581
582
Steve Block6ded16b2010-05-10 14:33:55 +0100583void ExitFrame::SetCallerFp(Address caller_fp) {
584 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
585}
586
587
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100588void ExitFrame::Iterate(ObjectVisitor* v) const {
589 // The arguments are traversed as part of the expression stack of
590 // the calling frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100592 v->VisitPointer(&code_slot());
593}
594
595
Steve Blocka7e24c12009-10-30 11:49:00 +0000596Address ExitFrame::GetCallerStackPointer() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100597 return fp() + ExitFrameConstants::kCallerSPOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +0000598}
599
600
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100601StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
602 if (fp == 0) return NONE;
603 Address sp = ComputeStackPointer(fp);
604 FillState(fp, sp, state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 DCHECK(*state->pc_address != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100606 return EXIT;
607}
608
609
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000610Address ExitFrame::ComputeStackPointer(Address fp) {
611 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
612}
613
614
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100615void ExitFrame::FillState(Address fp, Address sp, State* state) {
616 state->sp = sp;
617 state->fp = fp;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100618 state->pc_address = ResolveReturnAddressLocation(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620 // The constant pool recorded in the exit frame is not associated
621 // with the pc in this state (the return address into a C entry
622 // stub). ComputeCallerState will retrieve the constant pool
623 // together with the associated caller pc.
624 state->constant_pool_address = NULL;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100625}
626
627
Steve Blocka7e24c12009-10-30 11:49:00 +0000628Address StandardFrame::GetExpressionAddress(int n) const {
629 const int offset = StandardFrameConstants::kExpressionsOffset;
630 return fp() + offset - n * kPointerSize;
631}
632
Ben Murdoch097c5b22016-05-18 11:27:45 +0100633Address InterpretedFrame::GetExpressionAddress(int n) const {
634 const int offset = InterpreterFrameConstants::kExpressionsOffset;
635 return fp() + offset - n * kPointerSize;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000636}
637
Steve Blocka7e24c12009-10-30 11:49:00 +0000638int StandardFrame::ComputeExpressionsCount() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100639 Address base = GetExpressionAddress(0);
640 Address limit = sp() - kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641 DCHECK(base >= limit); // stack grows downwards
Steve Blocka7e24c12009-10-30 11:49:00 +0000642 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000643 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000644}
645
646
647void StandardFrame::ComputeCallerState(State* state) const {
648 state->sp = caller_sp();
649 state->fp = caller_fp();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100650 state->pc_address = ResolveReturnAddressLocation(
651 reinterpret_cast<Address*>(ComputePCAddress(fp())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 state->constant_pool_address =
653 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000654}
655
656
Steve Block6ded16b2010-05-10 14:33:55 +0100657void StandardFrame::SetCallerFp(Address caller_fp) {
658 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
659 caller_fp;
660}
661
662
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000663void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100664 // Make sure that we're not doing "safe" stack frame iteration. We cannot
665 // possibly find pointers in optimized frames in that state.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000666 DCHECK(can_access_heap_objects());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100667
668 // Compute the safepoint information.
669 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100670 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100671 Code* code = StackFrame::GetSafepointData(
Ben Murdoch8b112d22011-06-08 16:22:53 +0100672 isolate(), pc(), &safepoint_entry, &stack_slots);
Ben Murdochda12d292016-06-02 14:46:10 +0100673 unsigned slot_space = stack_slots * kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100674
Ben Murdochda12d292016-06-02 14:46:10 +0100675 // Determine the fixed header and spill slot area size.
676 int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp;
677 Object* marker =
678 Memory::Object_at(fp() + CommonFrameConstants::kContextOrFrameTypeOffset);
679 if (marker->IsSmi()) {
680 StackFrame::Type candidate =
681 static_cast<StackFrame::Type>(Smi::cast(marker)->value());
682 switch (candidate) {
683 case ENTRY:
684 case ENTRY_CONSTRUCT:
685 case EXIT:
686 case STUB_FAILURE_TRAMPOLINE:
687 case ARGUMENTS_ADAPTOR:
688 case STUB:
689 case INTERNAL:
690 case CONSTRUCT:
691 case JS_TO_WASM:
692 case WASM_TO_JS:
693 case WASM:
694 frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
695 break;
696 case JAVA_SCRIPT:
697 case OPTIMIZED:
698 case INTERPRETED:
699 // These frame types have a context, but they are actually stored
700 // in the place on the stack that one finds the frame type.
701 UNREACHABLE();
702 break;
703 case NONE:
704 case NUMBER_OF_TYPES:
705 case MANUAL:
706 UNREACHABLE();
707 break;
708 }
709 }
710 slot_space -=
711 (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp);
712
713 Object** frame_header_base = &Memory::Object_at(fp() - frame_header_size);
714 Object** frame_header_limit = &Memory::Object_at(fp());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100715 Object** parameters_base = &Memory::Object_at(sp());
Ben Murdochda12d292016-06-02 14:46:10 +0100716 Object** parameters_limit = frame_header_base - slot_space / kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100717
Ben Murdochb8e0da22011-05-16 14:20:40 +0100718 // Visit the parameters that may be on top of the saved registers.
719 if (safepoint_entry.argument_count() > 0) {
720 v->VisitPointers(parameters_base,
721 parameters_base + safepoint_entry.argument_count());
722 parameters_base += safepoint_entry.argument_count();
723 }
724
725 // Skip saved double registers.
726 if (safepoint_entry.has_doubles()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000727 // Number of doubles not known at snapshot time.
728 DCHECK(!isolate()->serializer_enabled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729 parameters_base +=
730 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
731 ->num_allocatable_double_registers() *
Ben Murdochb8e0da22011-05-16 14:20:40 +0100732 kDoubleSize / kPointerSize;
733 }
734
Ben Murdochb0fe1622011-05-05 13:52:32 +0100735 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100736 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100737 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100738 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100739 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
740 v->VisitPointer(parameters_base + reg_stack_index);
741 }
742 }
743 // Skip the words containing the register values.
744 parameters_base += kNumSafepointRegisters;
745 }
746
747 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100748 uint8_t* safepoint_bits = safepoint_entry.bits();
749 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100750
751 // Visit the rest of the parameters.
Ben Murdochda12d292016-06-02 14:46:10 +0100752 if (!is_js_to_wasm() && !is_wasm()) {
753 // Non-WASM frames have tagged values as parameters.
754 v->VisitPointers(parameters_base, parameters_limit);
755 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100756
757 // Visit pointer spill slots and locals.
758 for (unsigned index = 0; index < stack_slots; index++) {
759 int byte_index = index >> kBitsPerByteLog2;
760 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100761 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100762 v->VisitPointer(parameters_limit + index);
763 }
764 }
765
Ben Murdochb0fe1622011-05-05 13:52:32 +0100766 // Visit the return address in the callee and incoming arguments.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000767 IteratePc(v, pc_address(), constant_pool_address(), code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000768
Ben Murdochda12d292016-06-02 14:46:10 +0100769 if (!is_wasm() && !is_wasm_to_js()) {
770 // Visit the context in stub frame and JavaScript frame.
771 // Visit the function in JavaScript frame.
772 v->VisitPointers(frame_header_base, frame_header_limit);
773 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000774}
775
776
777void StubFrame::Iterate(ObjectVisitor* v) const {
778 IterateCompiledFrame(v);
779}
780
781
782Code* StubFrame::unchecked_code() const {
783 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
784}
785
786
787Address StubFrame::GetCallerStackPointer() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100788 return fp() + ExitFrameConstants::kCallerSPOffset;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789}
790
791
792int StubFrame::GetNumberOfIncomingArguments() const {
793 return 0;
794}
795
796
797void OptimizedFrame::Iterate(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000798 IterateCompiledFrame(v);
799}
800
801
802void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
803 Memory::Object_at(GetParameterSlot(index)) = value;
Steve Blocka7e24c12009-10-30 11:49:00 +0000804}
805
806
807bool JavaScriptFrame::IsConstructor() const {
808 Address fp = caller_fp();
809 if (has_adapted_arguments()) {
810 // Skip the arguments adaptor frame and look at the real caller.
811 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
812 }
813 return IsConstructFrame(fp);
814}
815
816
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000817bool JavaScriptFrame::HasInlinedFrames() const {
818 List<JSFunction*> functions(1);
819 GetFunctions(&functions);
820 return functions.length() > 1;
821}
822
823
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000824int JavaScriptFrame::GetArgumentsLength() const {
825 // If there is an arguments adaptor frame get the arguments length from it.
826 if (has_adapted_arguments()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100827 return ArgumentsAdaptorFrame::GetLength(caller_fp());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000828 } else {
829 return GetNumberOfIncomingArguments();
830 }
831}
832
833
Iain Merrick75681382010-08-19 15:07:18 +0100834Code* JavaScriptFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 return function()->code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000836}
837
838
Ben Murdoch8b112d22011-06-08 16:22:53 +0100839int JavaScriptFrame::GetNumberOfIncomingArguments() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000840 DCHECK(can_access_heap_objects() &&
Ben Murdoch8b112d22011-06-08 16:22:53 +0100841 isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
842
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000843 return function()->shared()->internal_formal_parameter_count();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100844}
845
846
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100847Address JavaScriptFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100848 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100849}
850
851
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 DCHECK(functions->length() == 0);
854 functions->Add(function());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100855}
856
857
858void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000859 DCHECK(functions->length() == 0);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100860 Code* code = LookupCode();
861 int offset = static_cast<int>(pc() - code->instruction_start());
862 AbstractCode* abstract_code = AbstractCode::cast(code);
863 FrameSummary summary(receiver(), function(), abstract_code, offset,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100864 IsConstructor());
865 functions->Add(summary);
866}
867
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000868int JavaScriptFrame::LookupExceptionHandlerInTable(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100869 int* stack_depth, HandlerTable::CatchPrediction* prediction) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870 Code* code = LookupCode();
871 DCHECK(!code->is_optimized_code());
872 HandlerTable* table = HandlerTable::cast(code->handler_table());
873 int pc_offset = static_cast<int>(pc() - code->entry());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100874 return table->LookupRange(pc_offset, stack_depth, prediction);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000875}
876
877
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
879 Address pc, FILE* file,
880 bool print_line_number) {
881 PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
882 function->PrintName(file);
883 int code_offset = static_cast<int>(pc - code->instruction_start());
884 PrintF(file, "+%d", code_offset);
885 if (print_line_number) {
886 SharedFunctionInfo* shared = function->shared();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100887 int source_pos = code->SourcePosition(code_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888 Object* maybe_script = shared->script();
889 if (maybe_script->IsScript()) {
890 Script* script = Script::cast(maybe_script);
891 int line = script->GetLineNumber(source_pos) + 1;
892 Object* script_name_raw = script->name();
893 if (script_name_raw->IsString()) {
894 String* script_name = String::cast(script->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000895 base::SmartArrayPointer<char> c_script_name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000896 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
897 PrintF(file, " at %s:%d", c_script_name.get(), line);
898 } else {
899 PrintF(file, " at <unknown>:%d", line);
900 }
901 } else {
902 PrintF(file, " at <unknown>:<unknown>");
903 }
904 }
905}
906
907
908void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100909 bool print_line_number) {
910 // constructor calls
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000911 DisallowHeapAllocation no_allocation;
912 JavaScriptFrameIterator it(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100913 while (!it.done()) {
914 if (it.frame()->is_java_script()) {
915 JavaScriptFrame* frame = it.frame();
916 if (frame->IsConstructor()) PrintF(file, "new ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917 PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
918 frame->pc(), file, print_line_number);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100919 if (print_args) {
920 // function arguments
921 // (we are intentionally only printing the actually
922 // supplied parameters, not all parameters required)
923 PrintF(file, "(this=");
924 frame->receiver()->ShortPrint(file);
925 const int length = frame->ComputeParametersCount();
926 for (int i = 0; i < length; i++) {
927 PrintF(file, ", ");
928 frame->GetParameter(i)->ShortPrint(file);
929 }
930 PrintF(file, ")");
931 }
932 break;
933 }
934 it.Advance();
935 }
936}
937
938
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000939void JavaScriptFrame::SaveOperandStack(FixedArray* store) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000940 int operands_count = store->length();
941 DCHECK_LE(operands_count, ComputeOperandsCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000942 for (int i = 0; i < operands_count; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000943 store->set(i, GetOperand(i));
944 }
945}
946
947
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948void JavaScriptFrame::RestoreOperandStack(FixedArray* store) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000949 int operands_count = store->length();
950 DCHECK_LE(operands_count, ComputeOperandsCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 for (int i = 0; i < operands_count; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000952 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
953 Memory::Object_at(GetOperandSlot(i)) = store->get(i);
954 }
955}
956
Ben Murdochda12d292016-06-02 14:46:10 +0100957namespace {
958
959bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) {
960 return code->is_turbofanned() && function->shared()->asm_function() &&
961 !FLAG_turbo_asm_deoptimization;
962}
963
964} // namespace
965
Ben Murdoch097c5b22016-05-18 11:27:45 +0100966FrameSummary::FrameSummary(Object* receiver, JSFunction* function,
967 AbstractCode* abstract_code, int code_offset,
968 bool is_constructor)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000969 : receiver_(receiver, function->GetIsolate()),
970 function_(function),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100971 abstract_code_(abstract_code),
972 code_offset_(code_offset),
Ben Murdochda12d292016-06-02 14:46:10 +0100973 is_constructor_(is_constructor) {
974 DCHECK(abstract_code->IsBytecodeArray() ||
975 Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION ||
976 CannotDeoptFromAsmCode(Code::cast(abstract_code), function));
977}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000978
Ben Murdochb0fe1622011-05-05 13:52:32 +0100979void FrameSummary::Print() {
980 PrintF("receiver: ");
981 receiver_->ShortPrint();
982 PrintF("\nfunction: ");
983 function_->shared()->DebugName()->ShortPrint();
984 PrintF("\ncode: ");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100985 abstract_code_->ShortPrint();
986 if (abstract_code_->IsCode()) {
987 Code* code = abstract_code_->GetCode();
988 if (code->kind() == Code::FUNCTION) PrintF(" UNOPT ");
Ben Murdochda12d292016-06-02 14:46:10 +0100989 if (code->kind() == Code::OPTIMIZED_FUNCTION) {
990 DCHECK(CannotDeoptFromAsmCode(code, *function()));
991 PrintF(" ASM ");
992 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100993 } else {
994 PrintF(" BYTECODE ");
995 }
996 PrintF("\npc: %d\n", code_offset_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100997}
998
999
1000void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001001 DCHECK(frames->length() == 0);
1002 DCHECK(is_optimized());
1003
1004 // Delegate to JS frame in absence of turbofan deoptimization.
1005 // TODO(turbofan): Revisit once we support deoptimization across the board.
Ben Murdochda12d292016-06-02 14:46:10 +01001006 Code* code = LookupCode();
1007 if (code->kind() == Code::BUILTIN ||
1008 CannotDeoptFromAsmCode(code, function())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001009 return JavaScriptFrame::Summarize(frames);
1010 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001011
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001012 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +01001013 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001014 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
1015 FixedArray* const literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001016
1017 TranslationIterator it(data->TranslationByteArray(),
1018 data->TranslationIndex(deopt_index)->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001019 Translation::Opcode frame_opcode =
1020 static_cast<Translation::Opcode>(it.Next());
1021 DCHECK_EQ(Translation::BEGIN, frame_opcode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001022 it.Next(); // Drop frame count.
1023 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001024
1025 // We create the summary in reverse order because the frames
1026 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001027 bool is_constructor = IsConstructor();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001028 while (jsframe_count != 0) {
1029 frame_opcode = static_cast<Translation::Opcode>(it.Next());
1030 if (frame_opcode == Translation::JS_FRAME ||
1031 frame_opcode == Translation::INTERPRETED_FRAME) {
1032 jsframe_count--;
Ben Murdochda12d292016-06-02 14:46:10 +01001033 BailoutId const bailout_id = BailoutId(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034 SharedFunctionInfo* const shared_info =
1035 SharedFunctionInfo::cast(literal_array->get(it.Next()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001036 it.Next(); // Skip height.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001037
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001038 // The translation commands are ordered and the function is always
1039 // at the first position, and the receiver is next.
1040 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
1041
1042 // Get the correct function in the optimized frame.
1043 JSFunction* function;
1044 if (opcode == Translation::LITERAL) {
1045 function = JSFunction::cast(literal_array->get(it.Next()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001046 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001047 CHECK_EQ(opcode, Translation::STACK_SLOT);
1048 function = JSFunction::cast(StackSlotAt(it.Next()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 }
1050 DCHECK_EQ(shared_info, function->shared());
1051
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001052 // If we are at a call, the receiver is always in a stack slot.
1053 // Otherwise we are not guaranteed to get the receiver value.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001054 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001055
1056 // Get the correct receiver in the optimized frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001057 Object* receiver;
Ben Murdoch257744e2011-11-30 15:57:28 +00001058 if (opcode == Translation::LITERAL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001059 receiver = literal_array->get(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001060 } else if (opcode == Translation::STACK_SLOT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001061 receiver = StackSlotAt(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001062 } else {
1063 // The receiver is not in a stack slot nor in a literal. We give up.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001064 it.Skip(Translation::NumberOfOperandsFor(opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065 // TODO(3029): Materializing a captured object (or duplicated
1066 // object) is hard, we return undefined for now. This breaks the
1067 // produced stack trace, as constructor frames aren't marked as
1068 // such anymore.
1069 receiver = isolate()->heap()->undefined_value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001070 }
1071
Ben Murdoch097c5b22016-05-18 11:27:45 +01001072 AbstractCode* abstract_code;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001073
Ben Murdoch097c5b22016-05-18 11:27:45 +01001074 unsigned code_offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001075 if (frame_opcode == Translation::JS_FRAME) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001076 Code* code = shared_info->code();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001077 DeoptimizationOutputData* const output_data =
1078 DeoptimizationOutputData::cast(code->deoptimization_data());
1079 unsigned const entry =
Ben Murdochda12d292016-06-02 14:46:10 +01001080 Deoptimizer::GetOutputInfo(output_data, bailout_id, shared_info);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001081 code_offset = FullCodeGenerator::PcField::decode(entry);
1082 abstract_code = AbstractCode::cast(code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001083 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 DCHECK_EQ(frame_opcode, Translation::INTERPRETED_FRAME);
Ben Murdochda12d292016-06-02 14:46:10 +01001085 // BailoutId points to the next bytecode in the bytecode aray. Subtract
1086 // 1 to get the end of current bytecode.
1087 code_offset = bailout_id.ToInt() - 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001088 abstract_code = AbstractCode::cast(shared_info->bytecode_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001089 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001090 FrameSummary summary(receiver, function, abstract_code, code_offset,
1091 is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001092 frames->Add(summary);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001093 is_constructor = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001094 } else if (frame_opcode == Translation::CONSTRUCT_STUB_FRAME) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001095 // The next encountered JS_FRAME will be marked as a constructor call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001096 it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001097 DCHECK(!is_constructor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001098 is_constructor = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001099 } else {
1100 // Skip over operands to advance to the next opcode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001102 }
1103 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001104 DCHECK(!is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001105}
1106
1107
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108int OptimizedFrame::LookupExceptionHandlerInTable(
1109 int* stack_slots, HandlerTable::CatchPrediction* prediction) {
1110 Code* code = LookupCode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001111 HandlerTable* table = HandlerTable::cast(code->handler_table());
1112 int pc_offset = static_cast<int>(pc() - code->entry());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001113 if (stack_slots) *stack_slots = code->stack_slots();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001114 return table->LookupReturn(pc_offset, prediction);
1115}
1116
1117
Ben Murdochb0fe1622011-05-05 13:52:32 +01001118DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001119 int* deopt_index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001120 DCHECK(is_optimized());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001121
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001122 JSFunction* opt_function = function();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001123 Code* code = opt_function->code();
1124
1125 // The code object may have been replaced by lazy deoptimization. Fall
1126 // back to a slow search in this case to find the original optimized
1127 // code object.
1128 if (!code->contains(pc())) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001129 code = isolate()->inner_pointer_to_code_cache()->
1130 GcSafeFindCodeForInnerPointer(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001131 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001132 DCHECK(code != NULL);
1133 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001134
Ben Murdochb8e0da22011-05-16 14:20:40 +01001135 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1136 *deopt_index = safepoint_entry.deoptimization_index();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001137 DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001138
1139 return DeoptimizationInputData::cast(code->deoptimization_data());
1140}
1141
1142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001143void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001144 DCHECK(functions->length() == 0);
1145 DCHECK(is_optimized());
1146
1147 // Delegate to JS frame in absence of turbofan deoptimization.
1148 // TODO(turbofan): Revisit once we support deoptimization across the board.
Ben Murdochda12d292016-06-02 14:46:10 +01001149 Code* code = LookupCode();
1150 if (code->kind() == Code::BUILTIN ||
1151 CannotDeoptFromAsmCode(code, function())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001152 return JavaScriptFrame::GetFunctions(functions);
1153 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001154
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001155 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +01001156 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
1158 FixedArray* const literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001159
1160 TranslationIterator it(data->TranslationByteArray(),
1161 data->TranslationIndex(deopt_index)->value());
1162 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001163 DCHECK_EQ(Translation::BEGIN, opcode);
1164 it.Next(); // Skip frame count.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001165 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001166
1167 // We insert the frames in reverse order because the frames
1168 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001169 while (jsframe_count != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001170 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171 // Skip over operands to advance to the next opcode.
1172 it.Skip(Translation::NumberOfOperandsFor(opcode));
1173 if (opcode == Translation::JS_FRAME ||
1174 opcode == Translation::INTERPRETED_FRAME) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001175 jsframe_count--;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001176
1177 // The translation commands are ordered and the function is always at the
1178 // first position.
1179 opcode = static_cast<Translation::Opcode>(it.Next());
1180
1181 // Get the correct function in the optimized frame.
1182 Object* function;
1183 if (opcode == Translation::LITERAL) {
1184 function = literal_array->get(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001186 CHECK_EQ(Translation::STACK_SLOT, opcode);
1187 function = StackSlotAt(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001188 }
1189 functions->Add(JSFunction::cast(function));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001190 }
1191 }
1192}
1193
1194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) {
1196 return StandardFrameConstants::kCallerSPOffset -
1197 ((slot_index + 1) * kPointerSize);
1198}
1199
1200
1201Object* OptimizedFrame::StackSlotAt(int index) const {
1202 return Memory::Object_at(fp() + StackSlotOffsetRelativeToFp(index));
1203}
1204
Ben Murdoch097c5b22016-05-18 11:27:45 +01001205int InterpretedFrame::LookupExceptionHandlerInTable(
1206 int* context_register, HandlerTable::CatchPrediction* prediction) {
1207 BytecodeArray* bytecode = function()->shared()->bytecode_array();
1208 HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
1209 int pc_offset = GetBytecodeOffset() + 1; // Point after current bytecode.
1210 return table->LookupRange(pc_offset, context_register, prediction);
1211}
1212
1213int InterpretedFrame::GetBytecodeOffset() const {
1214 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1215 DCHECK_EQ(
1216 InterpreterFrameConstants::kBytecodeOffsetFromFp,
1217 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1218 int raw_offset = Smi::cast(GetExpression(index))->value();
1219 return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
1220}
1221
1222void InterpretedFrame::PatchBytecodeOffset(int new_offset) {
1223 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1224 DCHECK_EQ(
1225 InterpreterFrameConstants::kBytecodeOffsetFromFp,
1226 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1227 int raw_offset = new_offset + BytecodeArray::kHeaderSize - kHeapObjectTag;
1228 SetExpression(index, Smi::FromInt(raw_offset));
1229}
1230
1231Object* InterpretedFrame::GetBytecodeArray() const {
1232 const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1233 DCHECK_EQ(
1234 InterpreterFrameConstants::kBytecodeArrayFromFp,
1235 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1236 return GetExpression(index);
1237}
1238
1239void InterpretedFrame::PatchBytecodeArray(Object* bytecode_array) {
1240 const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1241 DCHECK_EQ(
1242 InterpreterFrameConstants::kBytecodeArrayFromFp,
1243 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1244 SetExpression(index, bytecode_array);
1245}
1246
1247Object* InterpretedFrame::GetInterpreterRegister(int register_index) const {
1248 const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1249 DCHECK_EQ(
1250 InterpreterFrameConstants::kRegisterFilePointerFromFp,
1251 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1252 return GetExpression(index + register_index);
1253}
1254
1255void InterpretedFrame::Summarize(List<FrameSummary>* functions) {
1256 DCHECK(functions->length() == 0);
1257 AbstractCode* abstract_code =
1258 AbstractCode::cast(function()->shared()->bytecode_array());
1259 FrameSummary summary(receiver(), function(), abstract_code,
1260 GetBytecodeOffset(), IsConstructor());
1261 functions->Add(summary);
1262}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001263
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001264int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
1265 return Smi::cast(GetExpression(0))->value();
1266}
1267
1268
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001269Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001270 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001271}
1272
Ben Murdoch097c5b22016-05-18 11:27:45 +01001273int ArgumentsAdaptorFrame::GetLength(Address fp) {
1274 const int offset = ArgumentsAdaptorFrameConstants::kLengthOffset;
1275 return Smi::cast(Memory::Object_at(fp + offset))->value();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001276}
1277
Iain Merrick75681382010-08-19 15:07:18 +01001278Code* ArgumentsAdaptorFrame::unchecked_code() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001279 return isolate()->builtins()->builtin(
Steve Block44f0eee2011-05-26 01:26:41 +01001280 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +00001281}
1282
Ben Murdoch097c5b22016-05-18 11:27:45 +01001283Address InternalFrame::GetCallerStackPointer() const {
1284 // Internal frames have no arguments. The stack pointer of the
1285 // caller is at a fixed offset from the frame pointer.
1286 return fp() + StandardFrameConstants::kCallerSPOffset;
1287}
Steve Blocka7e24c12009-10-30 11:49:00 +00001288
Iain Merrick75681382010-08-19 15:07:18 +01001289Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001290 const int offset = InternalFrameConstants::kCodeOffset;
1291 Object* code = Memory::Object_at(fp() + offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292 DCHECK(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +01001293 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001294}
1295
1296
1297void StackFrame::PrintIndex(StringStream* accumulator,
1298 PrintMode mode,
1299 int index) {
1300 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1301}
1302
Ben Murdochda12d292016-06-02 14:46:10 +01001303void WasmFrame::Print(StringStream* accumulator, PrintMode mode,
1304 int index) const {
1305 accumulator->Add("wasm frame");
1306}
1307
1308Code* WasmFrame::unchecked_code() const {
1309 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
1310}
1311
1312void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); }
1313
1314Address WasmFrame::GetCallerStackPointer() const {
1315 return fp() + ExitFrameConstants::kCallerSPOffset;
1316}
Steve Blocka7e24c12009-10-30 11:49:00 +00001317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001318namespace {
1319
1320
1321void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared,
1322 Code* code) {
1323 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1324 std::ostringstream os;
1325 os << "--------- s o u r c e c o d e ---------\n"
1326 << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1327 << "\n-----------------------------------------\n";
1328 accumulator->Add(os.str().c_str());
1329 }
1330}
1331
1332
1333} // namespace
1334
1335
Steve Blocka7e24c12009-10-30 11:49:00 +00001336void JavaScriptFrame::Print(StringStream* accumulator,
1337 PrintMode mode,
1338 int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001339 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001340 Object* receiver = this->receiver();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341 JSFunction* function = this->function();
Steve Blocka7e24c12009-10-30 11:49:00 +00001342
1343 accumulator->PrintSecurityTokenIfChanged(function);
1344 PrintIndex(accumulator, mode, index);
1345 Code* code = NULL;
1346 if (IsConstructor()) accumulator->Add("new ");
1347 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +01001348
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001349 // Get scope information for nicer output, if possible. If code is NULL, or
1350 // doesn't contain scope info, scope_info will return 0 for the number of
1351 // parameters, stack local variables, context local variables, stack slots,
1352 // or context slots.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353 SharedFunctionInfo* shared = function->shared();
1354 ScopeInfo* scope_info = shared->scope_info();
1355 Object* script_obj = shared->script();
1356 if (script_obj->IsScript()) {
1357 Script* script = Script::cast(script_obj);
1358 accumulator->Add(" [");
1359 accumulator->PrintName(script->name());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001360
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001361 Address pc = this->pc();
1362 if (code != NULL && code->kind() == Code::FUNCTION &&
1363 pc >= code->instruction_start() && pc < code->instruction_end()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001364 int offset = static_cast<int>(pc - code->instruction_start());
1365 int source_pos = code->SourcePosition(offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001366 int line = script->GetLineNumber(source_pos) + 1;
1367 accumulator->Add(":%d", line);
1368 } else {
1369 int function_start_pos = shared->start_position();
1370 int line = script->GetLineNumber(function_start_pos) + 1;
1371 accumulator->Add(":~%d", line);
Steve Block6ded16b2010-05-10 14:33:55 +01001372 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001373
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001374 accumulator->Add("] [pc=%p] ", pc);
Steve Block6ded16b2010-05-10 14:33:55 +01001375 }
1376
Steve Blocka7e24c12009-10-30 11:49:00 +00001377 accumulator->Add("(this=%o", receiver);
1378
Steve Blocka7e24c12009-10-30 11:49:00 +00001379 // Print the parameters.
1380 int parameters_count = ComputeParametersCount();
1381 for (int i = 0; i < parameters_count; i++) {
1382 accumulator->Add(",");
1383 // If we have a name for the parameter we print it. Nameless
1384 // parameters are either because we have more actual parameters
1385 // than formal parameters or because we have no scope information.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001386 if (i < scope_info->ParameterCount()) {
1387 accumulator->PrintName(scope_info->ParameterName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001388 accumulator->Add("=");
1389 }
1390 accumulator->Add("%o", GetParameter(i));
1391 }
1392
1393 accumulator->Add(")");
1394 if (mode == OVERVIEW) {
1395 accumulator->Add("\n");
1396 return;
1397 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001398 if (is_optimized()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 accumulator->Add(" {\n// optimized frame\n");
1400 PrintFunctionSource(accumulator, shared, code);
1401 accumulator->Add("}\n");
Ben Murdoch257744e2011-11-30 15:57:28 +00001402 return;
1403 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001404 accumulator->Add(" {\n");
1405
1406 // Compute the number of locals and expression stack elements.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001407 int stack_locals_count = scope_info->StackLocalCount();
1408 int heap_locals_count = scope_info->ContextLocalCount();
Steve Blocka7e24c12009-10-30 11:49:00 +00001409 int expressions_count = ComputeExpressionsCount();
1410
1411 // Print stack-allocated local variables.
1412 if (stack_locals_count > 0) {
1413 accumulator->Add(" // stack-allocated locals\n");
1414 }
1415 for (int i = 0; i < stack_locals_count; i++) {
1416 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001417 accumulator->PrintName(scope_info->StackLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001418 accumulator->Add(" = ");
1419 if (i < expressions_count) {
1420 accumulator->Add("%o", GetExpression(i));
1421 } else {
1422 accumulator->Add("// no expression found - inconsistent frame?");
1423 }
1424 accumulator->Add("\n");
1425 }
1426
1427 // Try to get hold of the context of this frame.
1428 Context* context = NULL;
1429 if (this->context() != NULL && this->context()->IsContext()) {
1430 context = Context::cast(this->context());
1431 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001432 while (context->IsWithContext()) {
1433 context = context->previous();
1434 DCHECK(context != NULL);
1435 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001436
1437 // Print heap-allocated local variables.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001438 if (heap_locals_count > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001439 accumulator->Add(" // heap-allocated locals\n");
1440 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001441 for (int i = 0; i < heap_locals_count; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001442 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001443 accumulator->PrintName(scope_info->ContextLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001444 accumulator->Add(" = ");
1445 if (context != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001446 int index = Context::MIN_CONTEXT_SLOTS + i;
1447 if (index < context->length()) {
1448 accumulator->Add("%o", context->get(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00001449 } else {
1450 accumulator->Add(
1451 "// warning: missing context slot - inconsistent frame?");
1452 }
1453 } else {
1454 accumulator->Add("// warning: no context found - inconsistent frame?");
1455 }
1456 accumulator->Add("\n");
1457 }
1458
1459 // Print the expression stack.
1460 int expressions_start = stack_locals_count;
1461 if (expressions_start < expressions_count) {
1462 accumulator->Add(" // expression stack (top to bottom)\n");
1463 }
1464 for (int i = expressions_count - 1; i >= expressions_start; i--) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001465 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1466 }
1467
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001468 PrintFunctionSource(accumulator, shared, code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001469
1470 accumulator->Add("}\n\n");
1471}
1472
1473
1474void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1475 PrintMode mode,
1476 int index) const {
1477 int actual = ComputeParametersCount();
1478 int expected = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001479 JSFunction* function = this->function();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001480 expected = function->shared()->internal_formal_parameter_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00001481
1482 PrintIndex(accumulator, mode, index);
1483 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1484 if (mode == OVERVIEW) {
1485 accumulator->Add("\n");
1486 return;
1487 }
1488 accumulator->Add(" {\n");
1489
1490 // Print actual arguments.
1491 if (actual > 0) accumulator->Add(" // actual arguments\n");
1492 for (int i = 0; i < actual; i++) {
1493 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1494 if (expected != -1 && i >= expected) {
1495 accumulator->Add(" // not passed to callee");
1496 }
1497 accumulator->Add("\n");
1498 }
1499
1500 accumulator->Add("}\n\n");
1501}
1502
1503
1504void EntryFrame::Iterate(ObjectVisitor* v) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001505 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001506}
1507
1508
1509void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001510 const int offset = StandardFrameConstants::kLastObjectOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +00001511 Object** base = &Memory::Object_at(sp());
1512 Object** limit = &Memory::Object_at(fp() + offset) + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00001513 v->VisitPointers(base, limit);
1514}
1515
1516
1517void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1518 IterateExpressions(v);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001519 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001520}
1521
Steve Blocka7e24c12009-10-30 11:49:00 +00001522void InternalFrame::Iterate(ObjectVisitor* v) const {
1523 // Internal frames only have object pointers on the expression stack
1524 // as they never have any arguments.
1525 IterateExpressions(v);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001526 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001527}
1528
1529
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001530void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
1531 Object** base = &Memory::Object_at(sp());
Ben Murdochda12d292016-06-02 14:46:10 +01001532 Object** limit = &Memory::Object_at(
1533 fp() + StubFailureTrampolineFrameConstants::kFixedHeaderBottomOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001534 v->VisitPointers(base, limit);
Ben Murdochda12d292016-06-02 14:46:10 +01001535 base = &Memory::Object_at(fp() + StandardFrameConstants::kFunctionOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001536 const int offset = StandardFrameConstants::kLastObjectOffset;
1537 limit = &Memory::Object_at(fp() + offset) + 1;
1538 v->VisitPointers(base, limit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001539 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540}
1541
1542
1543Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
1544 return fp() + StandardFrameConstants::kCallerSPOffset;
1545}
1546
1547
1548Code* StubFailureTrampolineFrame::unchecked_code() const {
1549 Code* trampoline;
1550 StubFailureTrampolineStub(isolate(), NOT_JS_FUNCTION_STUB_MODE).
1551 FindCodeInCache(&trampoline);
1552 if (trampoline->contains(pc())) {
1553 return trampoline;
1554 }
1555
1556 StubFailureTrampolineStub(isolate(), JS_FUNCTION_STUB_MODE).
1557 FindCodeInCache(&trampoline);
1558 if (trampoline->contains(pc())) {
1559 return trampoline;
1560 }
1561
1562 UNREACHABLE();
1563 return NULL;
1564}
1565
1566
Steve Blocka7e24c12009-10-30 11:49:00 +00001567// -------------------------------------------------------------------------
1568
1569
1570JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001571 DCHECK(n >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001572 for (int i = 0; i <= n; i++) {
1573 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1574 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1575 iterator_.Advance();
1576 }
1577 UNREACHABLE();
1578 return NULL;
1579}
1580
1581
1582// -------------------------------------------------------------------------
1583
1584
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001585static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1586 MapWord map_word = object->map_word();
1587 return map_word.IsForwardingAddress() ?
1588 map_word.ToForwardingAddress()->map() : map_word.ToMap();
1589}
1590
1591
1592static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1593 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1594}
1595
1596
1597#ifdef DEBUG
1598static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1599 Map* map = GcSafeMapOfCodeSpaceObject(code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001600 DCHECK(map == code->GetHeap()->code_map());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001601 Address start = code->address();
1602 Address end = code->address() + code->SizeFromMap(map);
1603 return start <= addr && addr < end;
1604}
1605#endif
1606
1607
1608Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1609 Address inner_pointer) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001610 Code* code = reinterpret_cast<Code*>(object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001611 DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001612 return code;
1613}
1614
1615
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001616Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1617 Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001618 Heap* heap = isolate_->heap();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001619
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001620 // Check if the inner pointer points into a large object chunk.
1621 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1622 if (large_page != NULL) {
1623 return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1624 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001625
Ben Murdoch097c5b22016-05-18 11:27:45 +01001626 if (!heap->code_space()->Contains(inner_pointer)) {
1627 return nullptr;
1628 }
1629
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001630 // Iterate through the page until we reach the end or find an object starting
1631 // after the inner pointer.
1632 Page* page = Page::FromAddress(inner_pointer);
1633
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001634 DCHECK_EQ(page->owner(), heap->code_space());
1635 heap->mark_compact_collector()->SweepOrWaitUntilSweepingCompleted(page);
1636
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001637 Address addr = page->skip_list()->StartFor(inner_pointer);
1638
1639 Address top = heap->code_space()->top();
1640 Address limit = heap->code_space()->limit();
1641
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001642 while (true) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001643 if (addr == top && addr != limit) {
1644 addr = limit;
1645 continue;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001646 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001647
1648 HeapObject* obj = HeapObject::FromAddress(addr);
1649 int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1650 Address next_addr = addr + obj_size;
1651 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1652 addr = next_addr;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001653 }
1654}
1655
Ben Murdochb0fe1622011-05-05 13:52:32 +01001656
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001657InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1658 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001659 isolate_->counters()->pc_to_code()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001660 DCHECK(base::bits::IsPowerOfTwo32(kInnerPointerToCodeCacheSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001661 uint32_t hash = ComputeIntegerHash(ObjectAddressForHashing(inner_pointer),
1662 v8::internal::kZeroHashSeed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001663 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1664 InnerPointerToCodeCacheEntry* entry = cache(index);
1665 if (entry->inner_pointer == inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001666 isolate_->counters()->pc_to_code_cached()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001667 DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001668 } else {
1669 // Because this code may be interrupted by a profiling signal that
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001670 // also queries the cache, we cannot update inner_pointer before the code
1671 // has been set. Otherwise, we risk trying to use a cache entry before
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001672 // the code has been computed.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001673 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001674 entry->safepoint_entry.Reset();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001675 entry->inner_pointer = inner_pointer;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001676 }
1677 return entry;
1678}
1679
1680
1681// -------------------------------------------------------------------------
1682
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001684int NumRegs(RegList reglist) { return base::bits::CountPopulation(reglist); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001685
1686
1687struct JSCallerSavedCodeData {
Steve Block44f0eee2011-05-26 01:26:41 +01001688 int reg_code[kNumJSCallerSaved];
1689};
1690
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001691JSCallerSavedCodeData caller_saved_code_data;
Steve Block44f0eee2011-05-26 01:26:41 +01001692
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001693void SetUpJSCallerSavedCodeData() {
1694 int i = 0;
1695 for (int r = 0; r < kNumRegs; r++)
1696 if ((kJSCallerSaved & (1 << r)) != 0)
1697 caller_saved_code_data.reg_code[i++] = r;
1698
1699 DCHECK(i == kNumJSCallerSaved);
1700}
1701
Steve Block44f0eee2011-05-26 01:26:41 +01001702
1703int JSCallerSavedCode(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001704 DCHECK(0 <= n && n < kNumJSCallerSaved);
1705 return caller_saved_code_data.reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001706}
1707
1708
Steve Block6ded16b2010-05-10 14:33:55 +01001709#define DEFINE_WRAPPER(type, field) \
1710class field##_Wrapper : public ZoneObject { \
1711 public: /* NOLINT */ \
1712 field##_Wrapper(const field& original) : frame_(original) { \
1713 } \
1714 field frame_; \
1715};
1716STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1717#undef DEFINE_WRAPPER
1718
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001719static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
Steve Block6ded16b2010-05-10 14:33:55 +01001720#define FRAME_TYPE_CASE(type, field) \
1721 case StackFrame::type: { \
1722 field##_Wrapper* wrapper = \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001723 new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
Steve Block6ded16b2010-05-10 14:33:55 +01001724 return &wrapper->frame_; \
1725 }
1726
1727 switch (frame->type()) {
1728 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1729 default: UNREACHABLE();
1730 }
1731#undef FRAME_TYPE_CASE
1732 return NULL;
1733}
1734
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001735
1736Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
1737 ZoneList<StackFrame*> list(10, zone);
1738 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1739 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1740 list.Add(frame, zone);
Steve Block6ded16b2010-05-10 14:33:55 +01001741 }
1742 return list.ToVector();
1743}
1744
1745
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001746} // namespace internal
1747} // namespace v8