blob: f116fd2739f73f99da628f174454f25abf9e2354 [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
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/ast.h"
8#include "src/base/bits.h"
9#include "src/deoptimizer.h"
10#include "src/frames-inl.h"
11#include "src/full-codegen.h"
12#include "src/heap/mark-compact.h"
13#include "src/safepoint-table.h"
14#include "src/scopeinfo.h"
15#include "src/string-stream.h"
16#include "src/vm-state-inl.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000017
Steve Blocka7e24c12009-10-30 11:49:00 +000018namespace v8 {
19namespace internal {
20
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022ReturnAddressLocationResolver
23 StackFrame::return_address_location_resolver_ = NULL;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010024
25
Steve Blocka7e24c12009-10-30 11:49:00 +000026// Iterator that supports traversing the stack handlers of a
27// particular frame. Needs to know the top of the handler chain.
28class StackHandlerIterator BASE_EMBEDDED {
29 public:
30 StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
31 : limit_(frame->fp()), handler_(handler) {
32 // Make sure the handler has already been unwound to this frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033 DCHECK(frame->sp() <= handler->address());
Steve Blocka7e24c12009-10-30 11:49:00 +000034 }
35
36 StackHandler* handler() const { return handler_; }
37
38 bool done() {
39 return handler_ == NULL || handler_->address() > limit_;
40 }
41 void Advance() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +000043 handler_ = handler_->next();
44 }
45
46 private:
47 const Address limit_;
48 StackHandler* handler_;
49};
50
51
52// -------------------------------------------------------------------------
53
54
55#define INITIALIZE_SINGLETON(type, field) field##_(this),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
57 bool can_access_heap_objects)
Ben Murdoch8b112d22011-06-08 16:22:53 +010058 : isolate_(isolate),
59 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
60 frame_(NULL), handler_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061 can_access_heap_objects_(can_access_heap_objects) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010062}
Steve Blocka7e24c12009-10-30 11:49:00 +000063#undef INITIALIZE_SINGLETON
64
65
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066StackFrameIterator::StackFrameIterator(Isolate* isolate)
67 : StackFrameIteratorBase(isolate, true) {
68 Reset(isolate->thread_local_top());
69}
70
71
72StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
73 : StackFrameIteratorBase(isolate, true) {
74 Reset(t);
75}
76
77
78void StackFrameIterator::Advance() {
79 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +000080 // Compute the state of the calling frame before restoring
81 // callee-saved registers and unwinding handlers. This allows the
82 // frame code that computes the caller state to access the top
83 // handler and the value of any callee-saved register if needed.
84 StackFrame::State state;
85 StackFrame::Type type = frame_->GetCallerState(&state);
86
87 // Unwind handlers corresponding to the current frame.
88 StackHandlerIterator it(frame_, handler_);
89 while (!it.done()) it.Advance();
90 handler_ = it.handler();
91
92 // Advance to the calling frame.
93 frame_ = SingletonFor(type, &state);
94
95 // When we're done iterating over the stack frames, the handler
96 // chain must have been completely unwound.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000097 DCHECK(!done() || handler_ == NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +000098}
99
100
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101void StackFrameIterator::Reset(ThreadLocalTop* top) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000102 StackFrame::State state;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103 StackFrame::Type type = ExitFrame::GetStateForFramePointer(
104 Isolate::c_entry_fp(top), &state);
105 handler_ = StackHandler::FromAddress(Isolate::handler(top));
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100106 if (SingletonFor(type) == NULL) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000107 frame_ = SingletonFor(type, &state);
108}
109
110
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
Steve Blocka7e24c12009-10-30 11:49:00 +0000112 StackFrame::State* state) {
113 if (type == StackFrame::NONE) return NULL;
114 StackFrame* result = SingletonFor(type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 DCHECK(result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000116 result->state_ = *state;
117 return result;
118}
119
120
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000122#define FRAME_TYPE_CASE(type, field) \
123 case StackFrame::type: result = &field##_; break;
124
125 StackFrame* result = NULL;
126 switch (type) {
127 case StackFrame::NONE: return NULL;
128 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
129 default: break;
130 }
131 return result;
132
133#undef FRAME_TYPE_CASE
134}
135
136
137// -------------------------------------------------------------------------
138
139
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140JavaScriptFrameIterator::JavaScriptFrameIterator(
141 Isolate* isolate, StackFrame::Id id)
142 : iterator_(isolate) {
143 while (!done()) {
144 Advance();
145 if (frame()->id() == id) return;
146 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000147}
148
149
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150void JavaScriptFrameIterator::Advance() {
151 do {
152 iterator_.Advance();
153 } while (!iterator_.done() && !iterator_.frame()->is_java_script());
154}
155
156
157void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
158 if (!frame()->has_adapted_arguments()) return;
159 iterator_.Advance();
160 DCHECK(iterator_.frame()->is_arguments_adaptor());
161}
162
163
164// -------------------------------------------------------------------------
165
166
Ben Murdoch8b112d22011-06-08 16:22:53 +0100167StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
168 : JavaScriptFrameIterator(isolate) {
169 if (!done() && !IsValidFrame()) Advance();
170}
171
172
Steve Blocka7e24c12009-10-30 11:49:00 +0000173void StackTraceFrameIterator::Advance() {
174 while (true) {
175 JavaScriptFrameIterator::Advance();
176 if (done()) return;
Leon Clarke4515c472010-02-03 11:58:03 +0000177 if (IsValidFrame()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000178 }
179}
180
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181
Leon Clarke4515c472010-02-03 11:58:03 +0000182bool StackTraceFrameIterator::IsValidFrame() {
183 if (!frame()->function()->IsJSFunction()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 Object* script = frame()->function()->shared()->script();
Leon Clarke4515c472010-02-03 11:58:03 +0000185 // Don't show functions from native scripts to user.
186 return (script->IsScript() &&
187 Script::TYPE_NATIVE != Script::cast(script)->type()->value());
188}
189
Steve Blocka7e24c12009-10-30 11:49:00 +0000190
191// -------------------------------------------------------------------------
192
193
194SafeStackFrameIterator::SafeStackFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100195 Isolate* isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 Address fp, Address sp, Address js_entry_sp)
197 : StackFrameIteratorBase(isolate, false),
198 low_bound_(sp),
199 high_bound_(js_entry_sp),
200 top_frame_type_(StackFrame::NONE),
201 external_callback_scope_(isolate->external_callback_scope()) {
202 StackFrame::State state;
203 StackFrame::Type type;
Steve Block44f0eee2011-05-26 01:26:41 +0100204 ThreadLocalTop* top = isolate->thread_local_top();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 if (IsValidTop(top)) {
206 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
207 top_frame_type_ = type;
208 } else if (IsValidStackAddress(fp)) {
209 DCHECK(fp != NULL);
210 state.fp = fp;
211 state.sp = sp;
212 state.pc_address = StackFrame::ResolveReturnAddressLocation(
213 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
214 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
215 // we check only that kMarkerOffset is within the stack bounds and do
216 // compile time check that kContextOffset slot is pushed on the stack before
217 // kMarkerOffset.
218 STATIC_ASSERT(StandardFrameConstants::kMarkerOffset <
219 StandardFrameConstants::kContextOffset);
220 Address frame_marker = fp + StandardFrameConstants::kMarkerOffset;
221 if (IsValidStackAddress(frame_marker)) {
222 type = StackFrame::ComputeType(this, &state);
223 top_frame_type_ = type;
224 } else {
225 // Mark the frame as JAVA_SCRIPT if we cannot determine its type.
226 // The frame anyways will be skipped.
227 type = StackFrame::JAVA_SCRIPT;
228 // Top frame is incomplete so we cannot reliably determine its type.
229 top_frame_type_ = StackFrame::NONE;
230 }
231 } else {
232 return;
233 }
234 if (SingletonFor(type) == NULL) return;
235 frame_ = SingletonFor(type, &state);
236 if (frame_ == NULL) return;
237
238 Advance();
239
240 if (frame_ != NULL && !frame_->is_exit() &&
241 external_callback_scope_ != NULL &&
242 external_callback_scope_->scope_address() < frame_->fp()) {
243 // Skip top ExternalCallbackScope if we already advanced to a JS frame
244 // under it. Sampler will anyways take this top external callback.
245 external_callback_scope_ = external_callback_scope_->previous();
246 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100247}
248
249
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000250bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
251 Address c_entry_fp = Isolate::c_entry_fp(top);
252 if (!IsValidExitFrame(c_entry_fp)) return false;
253 // There should be at least one JS_ENTRY stack handler.
254 Address handler = Isolate::handler(top);
255 if (handler == NULL) return false;
256 // Check that there are no js frames on top of the native frames.
257 return c_entry_fp < handler;
258}
259
260
261void SafeStackFrameIterator::AdvanceOneFrame() {
262 DCHECK(!done());
263 StackFrame* last_frame = frame_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000264 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265 // Before advancing to the next stack frame, perform pointer validity tests.
266 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
267 frame_ = NULL;
268 return;
269 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000270
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 // Advance to the previous frame.
272 StackFrame::State state;
273 StackFrame::Type type = frame_->GetCallerState(&state);
274 frame_ = SingletonFor(type, &state);
275 if (frame_ == NULL) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000276
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000277 // Check that we have actually moved to the previous frame in the stack.
278 if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
279 frame_ = NULL;
280 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000281}
282
283
284bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
285 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
286}
287
288
289bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
290 StackFrame::State state;
291 if (frame->is_entry() || frame->is_entry_construct()) {
292 // See EntryFrame::GetCallerState. It computes the caller FP address
293 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
294 // sure that caller FP address is valid.
295 Address caller_fp = Memory::Address_at(
296 frame->fp() + EntryFrameConstants::kCallerFPOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 if (!IsValidExitFrame(caller_fp)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000298 } else if (frame->is_arguments_adaptor()) {
299 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
300 // the number of arguments is stored on stack as Smi. We need to check
301 // that it really an Smi.
302 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
303 GetExpression(0);
304 if (!number_of_args->IsSmi()) {
305 return false;
306 }
307 }
308 frame->ComputeCallerState(&state);
309 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310 SingletonFor(frame->GetCallerState(&state)) != NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000311}
312
313
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000314bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
315 if (!IsValidStackAddress(fp)) return false;
316 Address sp = ExitFrame::ComputeStackPointer(fp);
317 if (!IsValidStackAddress(sp)) return false;
318 StackFrame::State state;
319 ExitFrame::FillState(fp, sp, &state);
320 if (!IsValidStackAddress(reinterpret_cast<Address>(state.pc_address))) {
321 return false;
322 }
323 return *state.pc_address != NULL;
324}
325
326
327void SafeStackFrameIterator::Advance() {
328 while (true) {
329 AdvanceOneFrame();
330 if (done()) return;
331 if (frame_->is_java_script()) return;
332 if (frame_->is_exit() && external_callback_scope_) {
333 // Some of the EXIT frames may have ExternalCallbackScope allocated on
334 // top of them. In that case the scope corresponds to the first EXIT
335 // frame beneath it. There may be other EXIT frames on top of the
336 // ExternalCallbackScope, just skip them as we cannot collect any useful
337 // information about them.
338 if (external_callback_scope_->scope_address() < frame_->fp()) {
339 Address* callback_address =
340 external_callback_scope_->callback_address();
341 if (*callback_address != NULL) {
342 frame_->state_.pc_address = callback_address;
343 }
344 external_callback_scope_ = external_callback_scope_->previous();
345 DCHECK(external_callback_scope_ == NULL ||
346 external_callback_scope_->scope_address() > frame_->fp());
347 return;
348 }
349 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000350 }
351}
352
353
354// -------------------------------------------------------------------------
355
356
Ben Murdoch8b112d22011-06-08 16:22:53 +0100357Code* StackFrame::GetSafepointData(Isolate* isolate,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100358 Address inner_pointer,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100359 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100360 unsigned* stack_slots) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100361 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
362 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100363 if (!entry->safepoint_entry.is_valid()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100364 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365 DCHECK(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100366 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000367 DCHECK(entry->safepoint_entry.Equals(
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100368 entry->code->GetSafepointEntry(inner_pointer)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100369 }
370
371 // Fill in the results and return the code.
372 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100373 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100374 *stack_slots = code->stack_slots();
375 return code;
376}
377
378
Steve Blocka7e24c12009-10-30 11:49:00 +0000379bool StackFrame::HasHandler() const {
380 StackHandlerIterator it(this, top_handler());
381 return !it.done();
382}
383
Ben Murdochb0fe1622011-05-05 13:52:32 +0100384
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100385#ifdef DEBUG
386static bool GcSafeCodeContains(HeapObject* object, Address addr);
387#endif
388
389
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100390void StackFrame::IteratePc(ObjectVisitor* v,
391 Address* pc_address,
392 Code* holder) {
393 Address pc = *pc_address;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394 DCHECK(GcSafeCodeContains(holder, pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100395 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
396 Object* code = holder;
397 v->VisitPointer(&code);
398 if (code != holder) {
399 holder = reinterpret_cast<Code*>(code);
400 pc = holder->instruction_start() + pc_offset;
401 *pc_address = pc;
Steve Blocka7e24c12009-10-30 11:49:00 +0000402 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000403}
404
405
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100406void StackFrame::SetReturnAddressLocationResolver(
407 ReturnAddressLocationResolver resolver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000408 DCHECK(return_address_location_resolver_ == NULL);
409 return_address_location_resolver_ = resolver;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100410}
411
412
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
414 State* state) {
415 DCHECK(state->fp != NULL);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100416 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
417 return ARGUMENTS_ADAPTOR;
Steve Blocka7e24c12009-10-30 11:49:00 +0000418 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100419 // The marker and function offsets overlap. If the marker isn't a
420 // smi then the frame is a JavaScript frame -- and the marker is
421 // really the function.
422 const int offset = StandardFrameConstants::kMarkerOffset;
423 Object* marker = Memory::Object_at(state->fp + offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100424 if (!marker->IsSmi()) {
425 // If we're using a "safe" stack iterator, we treat optimized
426 // frames as normal JavaScript frames to avoid having to look
427 // into the heap to determine the state. This is safe as long
428 // as nobody tries to GC...
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000429 if (!iterator->can_access_heap_objects_) return JAVA_SCRIPT;
430 Code::Kind kind = GetContainingCode(iterator->isolate(),
431 *(state->pc_address))->kind();
432 DCHECK(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100433 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
434 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100435 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000436}
437
438
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000439#ifdef DEBUG
440bool StackFrame::can_access_heap_objects() const {
441 return iterator_->can_access_heap_objects_;
442}
443#endif
444
Steve Blocka7e24c12009-10-30 11:49:00 +0000445
446StackFrame::Type StackFrame::GetCallerState(State* state) const {
447 ComputeCallerState(state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448 return ComputeType(iterator_, state);
449}
450
451
452Address StackFrame::UnpaddedFP() const {
453#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
454 if (!is_optimized()) return fp();
455 int32_t alignment_state = Memory::int32_at(
456 fp() + JavaScriptFrameConstants::kDynamicAlignmentStateOffset);
457
458 return (alignment_state == kAlignmentPaddingPushed) ?
459 (fp() + kPointerSize) : fp();
460#else
461 return fp();
462#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000463}
464
465
Iain Merrick75681382010-08-19 15:07:18 +0100466Code* EntryFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000467 return isolate()->heap()->js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000468}
469
470
471void EntryFrame::ComputeCallerState(State* state) const {
472 GetCallerState(state);
473}
474
475
Steve Block6ded16b2010-05-10 14:33:55 +0100476void EntryFrame::SetCallerFp(Address caller_fp) {
477 const int offset = EntryFrameConstants::kCallerFPOffset;
478 Memory::Address_at(this->fp() + offset) = caller_fp;
479}
480
481
Steve Blocka7e24c12009-10-30 11:49:00 +0000482StackFrame::Type EntryFrame::GetCallerState(State* state) const {
483 const int offset = EntryFrameConstants::kCallerFPOffset;
484 Address fp = Memory::Address_at(this->fp() + offset);
485 return ExitFrame::GetStateForFramePointer(fp, state);
486}
487
488
Iain Merrick75681382010-08-19 15:07:18 +0100489Code* EntryConstructFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000490 return isolate()->heap()->js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000491}
492
493
Steve Blockd0582a62009-12-15 09:54:21 +0000494Object*& ExitFrame::code_slot() const {
495 const int offset = ExitFrameConstants::kCodeOffset;
496 return Memory::Object_at(fp() + offset);
497}
498
499
Iain Merrick75681382010-08-19 15:07:18 +0100500Code* ExitFrame::unchecked_code() const {
501 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000502}
503
504
505void ExitFrame::ComputeCallerState(State* state) const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100506 // Set up the caller state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 state->sp = caller_sp();
508 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100509 state->pc_address = ResolveReturnAddressLocation(
510 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 if (FLAG_enable_ool_constant_pool) {
512 state->constant_pool_address = reinterpret_cast<Address*>(
513 fp() + ExitFrameConstants::kConstantPoolOffset);
514 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000515}
516
517
Steve Block6ded16b2010-05-10 14:33:55 +0100518void ExitFrame::SetCallerFp(Address caller_fp) {
519 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
520}
521
522
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100523void ExitFrame::Iterate(ObjectVisitor* v) const {
524 // The arguments are traversed as part of the expression stack of
525 // the calling frame.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100526 IteratePc(v, pc_address(), LookupCode());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100527 v->VisitPointer(&code_slot());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000528 if (FLAG_enable_ool_constant_pool) {
529 v->VisitPointer(&constant_pool_slot());
530 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100531}
532
533
Steve Blocka7e24c12009-10-30 11:49:00 +0000534Address ExitFrame::GetCallerStackPointer() const {
535 return fp() + ExitFrameConstants::kCallerSPDisplacement;
536}
537
538
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100539StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
540 if (fp == 0) return NONE;
541 Address sp = ComputeStackPointer(fp);
542 FillState(fp, sp, state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543 DCHECK(*state->pc_address != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100544 return EXIT;
545}
546
547
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000548Address ExitFrame::ComputeStackPointer(Address fp) {
549 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
550}
551
552
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100553void ExitFrame::FillState(Address fp, Address sp, State* state) {
554 state->sp = sp;
555 state->fp = fp;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100556 state->pc_address = ResolveReturnAddressLocation(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000557 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
558 state->constant_pool_address =
559 reinterpret_cast<Address*>(fp + ExitFrameConstants::kConstantPoolOffset);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100560}
561
562
Steve Blocka7e24c12009-10-30 11:49:00 +0000563Address StandardFrame::GetExpressionAddress(int n) const {
564 const int offset = StandardFrameConstants::kExpressionsOffset;
565 return fp() + offset - n * kPointerSize;
566}
567
568
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000569Object* StandardFrame::GetExpression(Address fp, int index) {
570 return Memory::Object_at(GetExpressionAddress(fp, index));
571}
572
573
574Address StandardFrame::GetExpressionAddress(Address fp, int n) {
575 const int offset = StandardFrameConstants::kExpressionsOffset;
576 return fp + offset - n * kPointerSize;
577}
578
579
Steve Blocka7e24c12009-10-30 11:49:00 +0000580int StandardFrame::ComputeExpressionsCount() const {
581 const int offset =
582 StandardFrameConstants::kExpressionsOffset + kPointerSize;
583 Address base = fp() + offset;
584 Address limit = sp();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000585 DCHECK(base >= limit); // stack grows downwards
Steve Blocka7e24c12009-10-30 11:49:00 +0000586 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000587 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000588}
589
590
591void StandardFrame::ComputeCallerState(State* state) const {
592 state->sp = caller_sp();
593 state->fp = caller_fp();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100594 state->pc_address = ResolveReturnAddressLocation(
595 reinterpret_cast<Address*>(ComputePCAddress(fp())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000596 state->constant_pool_address =
597 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000598}
599
600
Steve Block6ded16b2010-05-10 14:33:55 +0100601void StandardFrame::SetCallerFp(Address caller_fp) {
602 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
603 caller_fp;
604}
605
606
Steve Blocka7e24c12009-10-30 11:49:00 +0000607bool StandardFrame::IsExpressionInsideHandler(int n) const {
608 Address address = GetExpressionAddress(n);
609 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
610 if (it.handler()->includes(address)) return true;
611 }
612 return false;
613}
614
615
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000616void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100617 // Make sure that we're not doing "safe" stack frame iteration. We cannot
618 // possibly find pointers in optimized frames in that state.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619 DCHECK(can_access_heap_objects());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100620
621 // Compute the safepoint information.
622 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100623 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100624 Code* code = StackFrame::GetSafepointData(
Ben Murdoch8b112d22011-06-08 16:22:53 +0100625 isolate(), pc(), &safepoint_entry, &stack_slots);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100626 unsigned slot_space = stack_slots * kPointerSize;
627
Ben Murdoch8b112d22011-06-08 16:22:53 +0100628 // Visit the outgoing parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100629 Object** parameters_base = &Memory::Object_at(sp());
630 Object** parameters_limit = &Memory::Object_at(
631 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
632
Ben Murdochb8e0da22011-05-16 14:20:40 +0100633 // Visit the parameters that may be on top of the saved registers.
634 if (safepoint_entry.argument_count() > 0) {
635 v->VisitPointers(parameters_base,
636 parameters_base + safepoint_entry.argument_count());
637 parameters_base += safepoint_entry.argument_count();
638 }
639
640 // Skip saved double registers.
641 if (safepoint_entry.has_doubles()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000642 // Number of doubles not known at snapshot time.
643 DCHECK(!isolate()->serializer_enabled());
644 parameters_base += DoubleRegister::NumAllocatableRegisters() *
Ben Murdochb8e0da22011-05-16 14:20:40 +0100645 kDoubleSize / kPointerSize;
646 }
647
Ben Murdochb0fe1622011-05-05 13:52:32 +0100648 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100649 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100650 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100651 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100652 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
653 v->VisitPointer(parameters_base + reg_stack_index);
654 }
655 }
656 // Skip the words containing the register values.
657 parameters_base += kNumSafepointRegisters;
658 }
659
660 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100661 uint8_t* safepoint_bits = safepoint_entry.bits();
662 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100663
664 // Visit the rest of the parameters.
665 v->VisitPointers(parameters_base, parameters_limit);
666
667 // Visit pointer spill slots and locals.
668 for (unsigned index = 0; index < stack_slots; index++) {
669 int byte_index = index >> kBitsPerByteLog2;
670 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100671 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100672 v->VisitPointer(parameters_limit + index);
673 }
674 }
675
Ben Murdochb0fe1622011-05-05 13:52:32 +0100676 // Visit the return address in the callee and incoming arguments.
677 IteratePc(v, pc_address(), code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000678
679 // Visit the context in stub frame and JavaScript frame.
680 // Visit the function in JavaScript frame.
681 Object** fixed_base = &Memory::Object_at(
682 fp() + StandardFrameConstants::kMarkerOffset);
683 Object** fixed_limit = &Memory::Object_at(fp());
684 v->VisitPointers(fixed_base, fixed_limit);
685}
686
687
688void StubFrame::Iterate(ObjectVisitor* v) const {
689 IterateCompiledFrame(v);
690}
691
692
693Code* StubFrame::unchecked_code() const {
694 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
695}
696
697
698Address StubFrame::GetCallerStackPointer() const {
699 return fp() + ExitFrameConstants::kCallerSPDisplacement;
700}
701
702
703int StubFrame::GetNumberOfIncomingArguments() const {
704 return 0;
705}
706
707
708void OptimizedFrame::Iterate(ObjectVisitor* v) const {
709#ifdef DEBUG
710 // Make sure that optimized frames do not contain any stack handlers.
711 StackHandlerIterator it(this, top_handler());
712 DCHECK(it.done());
713#endif
714
715 IterateCompiledFrame(v);
716}
717
718
719void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
720 Memory::Object_at(GetParameterSlot(index)) = value;
Steve Blocka7e24c12009-10-30 11:49:00 +0000721}
722
723
724bool JavaScriptFrame::IsConstructor() const {
725 Address fp = caller_fp();
726 if (has_adapted_arguments()) {
727 // Skip the arguments adaptor frame and look at the real caller.
728 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
729 }
730 return IsConstructFrame(fp);
731}
732
733
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000734int JavaScriptFrame::GetArgumentsLength() const {
735 // If there is an arguments adaptor frame get the arguments length from it.
736 if (has_adapted_arguments()) {
737 return Smi::cast(GetExpression(caller_fp(), 0))->value();
738 } else {
739 return GetNumberOfIncomingArguments();
740 }
741}
742
743
Iain Merrick75681382010-08-19 15:07:18 +0100744Code* JavaScriptFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000745 return function()->code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000746}
747
748
Ben Murdoch8b112d22011-06-08 16:22:53 +0100749int JavaScriptFrame::GetNumberOfIncomingArguments() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000750 DCHECK(can_access_heap_objects() &&
Ben Murdoch8b112d22011-06-08 16:22:53 +0100751 isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
752
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753 return function()->shared()->formal_parameter_count();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100754}
755
756
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100757Address JavaScriptFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100758 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100759}
760
761
Ben Murdochb0fe1622011-05-05 13:52:32 +0100762void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000763 DCHECK(functions->length() == 0);
764 functions->Add(function());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100765}
766
767
768void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000769 DCHECK(functions->length() == 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100770 Code* code_pointer = LookupCode();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100771 int offset = static_cast<int>(pc() - code_pointer->address());
772 FrameSummary summary(receiver(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000773 function(),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100774 code_pointer,
775 offset,
776 IsConstructor());
777 functions->Add(summary);
778}
779
780
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
782 Address pc, FILE* file,
783 bool print_line_number) {
784 PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
785 function->PrintName(file);
786 int code_offset = static_cast<int>(pc - code->instruction_start());
787 PrintF(file, "+%d", code_offset);
788 if (print_line_number) {
789 SharedFunctionInfo* shared = function->shared();
790 int source_pos = code->SourcePosition(pc);
791 Object* maybe_script = shared->script();
792 if (maybe_script->IsScript()) {
793 Script* script = Script::cast(maybe_script);
794 int line = script->GetLineNumber(source_pos) + 1;
795 Object* script_name_raw = script->name();
796 if (script_name_raw->IsString()) {
797 String* script_name = String::cast(script->name());
798 SmartArrayPointer<char> c_script_name =
799 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
800 PrintF(file, " at %s:%d", c_script_name.get(), line);
801 } else {
802 PrintF(file, " at <unknown>:%d", line);
803 }
804 } else {
805 PrintF(file, " at <unknown>:<unknown>");
806 }
807 }
808}
809
810
811void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100812 bool print_line_number) {
813 // constructor calls
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000814 DisallowHeapAllocation no_allocation;
815 JavaScriptFrameIterator it(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100816 while (!it.done()) {
817 if (it.frame()->is_java_script()) {
818 JavaScriptFrame* frame = it.frame();
819 if (frame->IsConstructor()) PrintF(file, "new ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000820 PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
821 frame->pc(), file, print_line_number);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100822 if (print_args) {
823 // function arguments
824 // (we are intentionally only printing the actually
825 // supplied parameters, not all parameters required)
826 PrintF(file, "(this=");
827 frame->receiver()->ShortPrint(file);
828 const int length = frame->ComputeParametersCount();
829 for (int i = 0; i < length; i++) {
830 PrintF(file, ", ");
831 frame->GetParameter(i)->ShortPrint(file);
832 }
833 PrintF(file, ")");
834 }
835 break;
836 }
837 it.Advance();
838 }
839}
840
841
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000842void JavaScriptFrame::SaveOperandStack(FixedArray* store,
843 int* stack_handler_index) const {
844 int operands_count = store->length();
845 DCHECK_LE(operands_count, ComputeOperandsCount());
846
847 // Visit the stack in LIFO order, saving operands and stack handlers into the
848 // array. The saved stack handlers store a link to the next stack handler,
849 // which will allow RestoreOperandStack to rewind the handlers.
850 StackHandlerIterator it(this, top_handler());
851 int i = operands_count - 1;
852 *stack_handler_index = -1;
853 for (; !it.done(); it.Advance()) {
854 StackHandler* handler = it.handler();
855 // Save operands pushed after the handler was pushed.
856 for (; GetOperandSlot(i) < handler->address(); i--) {
857 store->set(i, GetOperand(i));
858 }
859 DCHECK_GE(i + 1, StackHandlerConstants::kSlotCount);
860 DCHECK_EQ(handler->address(), GetOperandSlot(i));
861 int next_stack_handler_index = i + 1 - StackHandlerConstants::kSlotCount;
862 handler->Unwind(isolate(), store, next_stack_handler_index,
863 *stack_handler_index);
864 *stack_handler_index = next_stack_handler_index;
865 i -= StackHandlerConstants::kSlotCount;
866 }
867
868 // Save any remaining operands.
869 for (; i >= 0; i--) {
870 store->set(i, GetOperand(i));
871 }
872}
873
874
875void JavaScriptFrame::RestoreOperandStack(FixedArray* store,
876 int stack_handler_index) {
877 int operands_count = store->length();
878 DCHECK_LE(operands_count, ComputeOperandsCount());
879 int i = 0;
880 while (i <= stack_handler_index) {
881 if (i < stack_handler_index) {
882 // An operand.
883 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
884 Memory::Object_at(GetOperandSlot(i)) = store->get(i);
885 i++;
886 } else {
887 // A stack handler.
888 DCHECK_EQ(i, stack_handler_index);
889 // The FixedArray store grows up. The stack grows down. So the operand
890 // slot for i actually points to the bottom of the top word in the
891 // handler. The base of the StackHandler* is the address of the bottom
892 // word, which will be the last slot that is in the handler.
893 int handler_slot_index = i + StackHandlerConstants::kSlotCount - 1;
894 StackHandler *handler =
895 StackHandler::FromAddress(GetOperandSlot(handler_slot_index));
896 stack_handler_index = handler->Rewind(isolate(), store, i, fp());
897 i += StackHandlerConstants::kSlotCount;
898 }
899 }
900
901 for (; i < operands_count; i++) {
902 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
903 Memory::Object_at(GetOperandSlot(i)) = store->get(i);
904 }
905}
906
907
Ben Murdochb0fe1622011-05-05 13:52:32 +0100908void FrameSummary::Print() {
909 PrintF("receiver: ");
910 receiver_->ShortPrint();
911 PrintF("\nfunction: ");
912 function_->shared()->DebugName()->ShortPrint();
913 PrintF("\ncode: ");
914 code_->ShortPrint();
915 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
916 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
917 PrintF("\npc: %d\n", offset_);
918}
919
920
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000921JSFunction* OptimizedFrame::LiteralAt(FixedArray* literal_array,
922 int literal_id) {
923 if (literal_id == Translation::kSelfLiteralId) {
924 return function();
925 }
926
927 return JSFunction::cast(literal_array->get(literal_id));
928}
929
930
Ben Murdochb0fe1622011-05-05 13:52:32 +0100931void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000932 DCHECK(frames->length() == 0);
933 DCHECK(is_optimized());
934
935 // Delegate to JS frame in absence of turbofan deoptimization.
936 // TODO(turbofan): Revisit once we support deoptimization across the board.
937 if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
938 return JavaScriptFrame::Summarize(frames);
939 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100940
Steve Block1e0659c2011-05-24 12:43:12 +0100941 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100942 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000943 FixedArray* literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100944
945 // BUG(3243555): Since we don't have a lazy-deopt registered at
946 // throw-statements, we can't use the translation at the call-site of
947 // throw. An entry with no deoptimization index indicates a call-site
948 // without a lazy-deopt. As a consequence we are not allowed to inline
949 // functions containing throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950 DCHECK(deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100951
952 TranslationIterator it(data->TranslationByteArray(),
953 data->TranslationIndex(deopt_index)->value());
954 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000955 DCHECK(opcode == Translation::BEGIN);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100956 it.Next(); // Drop frame count.
957 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100958
959 // We create the summary in reverse order because the frames
960 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100961 bool is_constructor = IsConstructor();
962 int i = jsframe_count;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100963 while (i > 0) {
964 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100965 if (opcode == Translation::JS_FRAME) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100966 i--;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967 BailoutId ast_id = BailoutId(it.Next());
968 JSFunction* function = LiteralAt(literal_array, it.Next());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100969 it.Next(); // Skip height.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100970
971 // The translation commands are ordered and the receiver is always
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000972 // at the first position.
973 // If we are at a call, the receiver is always in a stack slot.
974 // Otherwise we are not guaranteed to get the receiver value.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100975 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch257744e2011-11-30 15:57:28 +0000976 int index = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100977
978 // Get the correct receiver in the optimized frame.
979 Object* receiver = NULL;
Ben Murdoch257744e2011-11-30 15:57:28 +0000980 if (opcode == Translation::LITERAL) {
981 receiver = data->LiteralArray()->get(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000982 } else if (opcode == Translation::STACK_SLOT) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000983 // Positive index means the value is spilled to the locals
984 // area. Negative means it is stored in the incoming parameter
985 // area.
986 if (index >= 0) {
987 receiver = GetExpression(index);
988 } else {
989 // Index -1 overlaps with last parameter, -n with the first parameter,
990 // (-n - 1) with the receiver with n being the number of parameters
991 // of the outermost, optimized frame.
992 int parameter_count = ComputeParametersCount();
993 int parameter_index = index + parameter_count;
994 receiver = (parameter_index == -1)
995 ? this->receiver()
996 : this->GetParameter(parameter_index);
997 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 } else {
999 // The receiver is not in a stack slot nor in a literal. We give up.
1000 // TODO(3029): Materializing a captured object (or duplicated
1001 // object) is hard, we return undefined for now. This breaks the
1002 // produced stack trace, as constructor frames aren't marked as
1003 // such anymore.
1004 receiver = isolate()->heap()->undefined_value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001005 }
1006
1007 Code* code = function->shared()->code();
1008 DeoptimizationOutputData* output_data =
1009 DeoptimizationOutputData::cast(code->deoptimization_data());
1010 unsigned entry = Deoptimizer::GetOutputInfo(output_data,
1011 ast_id,
1012 function->shared());
1013 unsigned pc_offset =
1014 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001015 DCHECK(pc_offset > 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001016
1017 FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
1018 frames->Add(summary);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001019 is_constructor = false;
1020 } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) {
1021 // The next encountered JS_FRAME will be marked as a constructor call.
1022 it.Skip(Translation::NumberOfOperandsFor(opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001023 DCHECK(!is_constructor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001024 is_constructor = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001025 } else {
1026 // Skip over operands to advance to the next opcode.
1027 it.Skip(Translation::NumberOfOperandsFor(opcode));
1028 }
1029 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030 DCHECK(!is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001031}
1032
1033
1034DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
1035 int* deopt_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001036 DCHECK(is_optimized());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001037
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001038 JSFunction* opt_function = function();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001039 Code* code = opt_function->code();
1040
1041 // The code object may have been replaced by lazy deoptimization. Fall
1042 // back to a slow search in this case to find the original optimized
1043 // code object.
1044 if (!code->contains(pc())) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001045 code = isolate()->inner_pointer_to_code_cache()->
1046 GcSafeFindCodeForInnerPointer(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001047 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048 DCHECK(code != NULL);
1049 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001050
Ben Murdochb8e0da22011-05-16 14:20:40 +01001051 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1052 *deopt_index = safepoint_entry.deoptimization_index();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001053 DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001054
1055 return DeoptimizationInputData::cast(code->deoptimization_data());
1056}
1057
1058
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001059int OptimizedFrame::GetInlineCount() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001060 DCHECK(is_optimized());
1061
1062 // Delegate to JS frame in absence of turbofan deoptimization.
1063 // TODO(turbofan): Revisit once we support deoptimization across the board.
1064 if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
1065 return JavaScriptFrame::GetInlineCount();
1066 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001067
1068 int deopt_index = Safepoint::kNoDeoptimizationIndex;
1069 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
1070
1071 TranslationIterator it(data->TranslationByteArray(),
1072 data->TranslationIndex(deopt_index)->value());
1073 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001074 DCHECK(opcode == Translation::BEGIN);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001075 USE(opcode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001076 it.Next(); // Drop frame count.
1077 int jsframe_count = it.Next();
1078 return jsframe_count;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001079}
1080
1081
Ben Murdochb0fe1622011-05-05 13:52:32 +01001082void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083 DCHECK(functions->length() == 0);
1084 DCHECK(is_optimized());
1085
1086 // Delegate to JS frame in absence of turbofan deoptimization.
1087 // TODO(turbofan): Revisit once we support deoptimization across the board.
1088 if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
1089 return JavaScriptFrame::GetFunctions(functions);
1090 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001091
Steve Block1e0659c2011-05-24 12:43:12 +01001092 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001093 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001094 FixedArray* literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001095
1096 TranslationIterator it(data->TranslationByteArray(),
1097 data->TranslationIndex(deopt_index)->value());
1098 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001099 DCHECK(opcode == Translation::BEGIN);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001100 it.Next(); // Drop frame count.
1101 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001102
1103 // We insert the frames in reverse order because the frames
1104 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001105 while (jsframe_count > 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001106 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001107 if (opcode == Translation::JS_FRAME) {
1108 jsframe_count--;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001109 it.Next(); // Skip ast id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001110 JSFunction* function = LiteralAt(literal_array, it.Next());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001111 it.Next(); // Skip height.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001112 functions->Add(function);
1113 } else {
1114 // Skip over operands to advance to the next opcode.
1115 it.Skip(Translation::NumberOfOperandsFor(opcode));
1116 }
1117 }
1118}
1119
1120
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001121int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
1122 return Smi::cast(GetExpression(0))->value();
1123}
1124
1125
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001126Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001127 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001128}
1129
1130
1131Address InternalFrame::GetCallerStackPointer() const {
1132 // Internal frames have no arguments. The stack pointer of the
1133 // caller is at a fixed offset from the frame pointer.
1134 return fp() + StandardFrameConstants::kCallerSPOffset;
1135}
1136
1137
Iain Merrick75681382010-08-19 15:07:18 +01001138Code* ArgumentsAdaptorFrame::unchecked_code() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001139 return isolate()->builtins()->builtin(
Steve Block44f0eee2011-05-26 01:26:41 +01001140 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +00001141}
1142
1143
Iain Merrick75681382010-08-19 15:07:18 +01001144Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001145 const int offset = InternalFrameConstants::kCodeOffset;
1146 Object* code = Memory::Object_at(fp() + offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001147 DCHECK(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +01001148 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001149}
1150
1151
1152void StackFrame::PrintIndex(StringStream* accumulator,
1153 PrintMode mode,
1154 int index) {
1155 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1156}
1157
1158
1159void JavaScriptFrame::Print(StringStream* accumulator,
1160 PrintMode mode,
1161 int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001162 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001163 Object* receiver = this->receiver();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001164 JSFunction* function = this->function();
Steve Blocka7e24c12009-10-30 11:49:00 +00001165
1166 accumulator->PrintSecurityTokenIfChanged(function);
1167 PrintIndex(accumulator, mode, index);
1168 Code* code = NULL;
1169 if (IsConstructor()) accumulator->Add("new ");
1170 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +01001171
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001172 // Get scope information for nicer output, if possible. If code is NULL, or
1173 // doesn't contain scope info, scope_info will return 0 for the number of
1174 // parameters, stack local variables, context local variables, stack slots,
1175 // or context slots.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001176 SharedFunctionInfo* shared = function->shared();
1177 ScopeInfo* scope_info = shared->scope_info();
1178 Object* script_obj = shared->script();
1179 if (script_obj->IsScript()) {
1180 Script* script = Script::cast(script_obj);
1181 accumulator->Add(" [");
1182 accumulator->PrintName(script->name());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001183
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001184 Address pc = this->pc();
1185 if (code != NULL && code->kind() == Code::FUNCTION &&
1186 pc >= code->instruction_start() && pc < code->instruction_end()) {
1187 int source_pos = code->SourcePosition(pc);
1188 int line = script->GetLineNumber(source_pos) + 1;
1189 accumulator->Add(":%d", line);
1190 } else {
1191 int function_start_pos = shared->start_position();
1192 int line = script->GetLineNumber(function_start_pos) + 1;
1193 accumulator->Add(":~%d", line);
Steve Block6ded16b2010-05-10 14:33:55 +01001194 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001195
1196 accumulator->Add("] ");
Steve Block6ded16b2010-05-10 14:33:55 +01001197 }
1198
Steve Blocka7e24c12009-10-30 11:49:00 +00001199 accumulator->Add("(this=%o", receiver);
1200
Steve Blocka7e24c12009-10-30 11:49:00 +00001201 // Print the parameters.
1202 int parameters_count = ComputeParametersCount();
1203 for (int i = 0; i < parameters_count; i++) {
1204 accumulator->Add(",");
1205 // If we have a name for the parameter we print it. Nameless
1206 // parameters are either because we have more actual parameters
1207 // than formal parameters or because we have no scope information.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001208 if (i < scope_info->ParameterCount()) {
1209 accumulator->PrintName(scope_info->ParameterName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001210 accumulator->Add("=");
1211 }
1212 accumulator->Add("%o", GetParameter(i));
1213 }
1214
1215 accumulator->Add(")");
1216 if (mode == OVERVIEW) {
1217 accumulator->Add("\n");
1218 return;
1219 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001220 if (is_optimized()) {
1221 accumulator->Add(" {\n// optimized frame\n}\n");
1222 return;
1223 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001224 accumulator->Add(" {\n");
1225
1226 // Compute the number of locals and expression stack elements.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001227 int stack_locals_count = scope_info->StackLocalCount();
1228 int heap_locals_count = scope_info->ContextLocalCount();
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 int expressions_count = ComputeExpressionsCount();
1230
1231 // Print stack-allocated local variables.
1232 if (stack_locals_count > 0) {
1233 accumulator->Add(" // stack-allocated locals\n");
1234 }
1235 for (int i = 0; i < stack_locals_count; i++) {
1236 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001237 accumulator->PrintName(scope_info->StackLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 accumulator->Add(" = ");
1239 if (i < expressions_count) {
1240 accumulator->Add("%o", GetExpression(i));
1241 } else {
1242 accumulator->Add("// no expression found - inconsistent frame?");
1243 }
1244 accumulator->Add("\n");
1245 }
1246
1247 // Try to get hold of the context of this frame.
1248 Context* context = NULL;
1249 if (this->context() != NULL && this->context()->IsContext()) {
1250 context = Context::cast(this->context());
1251 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001252 while (context->IsWithContext()) {
1253 context = context->previous();
1254 DCHECK(context != NULL);
1255 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001256
1257 // Print heap-allocated local variables.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001258 if (heap_locals_count > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001259 accumulator->Add(" // heap-allocated locals\n");
1260 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001261 for (int i = 0; i < heap_locals_count; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001262 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001263 accumulator->PrintName(scope_info->ContextLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001264 accumulator->Add(" = ");
1265 if (context != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001266 int index = Context::MIN_CONTEXT_SLOTS + i;
1267 if (index < context->length()) {
1268 accumulator->Add("%o", context->get(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00001269 } else {
1270 accumulator->Add(
1271 "// warning: missing context slot - inconsistent frame?");
1272 }
1273 } else {
1274 accumulator->Add("// warning: no context found - inconsistent frame?");
1275 }
1276 accumulator->Add("\n");
1277 }
1278
1279 // Print the expression stack.
1280 int expressions_start = stack_locals_count;
1281 if (expressions_start < expressions_count) {
1282 accumulator->Add(" // expression stack (top to bottom)\n");
1283 }
1284 for (int i = expressions_count - 1; i >= expressions_start; i--) {
1285 if (IsExpressionInsideHandler(i)) continue;
1286 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1287 }
1288
1289 // Print details about the function.
1290 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 OStringStream os;
1292 SharedFunctionInfo* shared = function->shared();
1293 os << "--------- s o u r c e c o d e ---------\n"
1294 << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1295 << "\n-----------------------------------------\n";
1296 accumulator->Add(os.c_str());
Steve Blocka7e24c12009-10-30 11:49:00 +00001297 }
1298
1299 accumulator->Add("}\n\n");
1300}
1301
1302
1303void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1304 PrintMode mode,
1305 int index) const {
1306 int actual = ComputeParametersCount();
1307 int expected = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001308 JSFunction* function = this->function();
1309 expected = function->shared()->formal_parameter_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00001310
1311 PrintIndex(accumulator, mode, index);
1312 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1313 if (mode == OVERVIEW) {
1314 accumulator->Add("\n");
1315 return;
1316 }
1317 accumulator->Add(" {\n");
1318
1319 // Print actual arguments.
1320 if (actual > 0) accumulator->Add(" // actual arguments\n");
1321 for (int i = 0; i < actual; i++) {
1322 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1323 if (expected != -1 && i >= expected) {
1324 accumulator->Add(" // not passed to callee");
1325 }
1326 accumulator->Add("\n");
1327 }
1328
1329 accumulator->Add("}\n\n");
1330}
1331
1332
1333void EntryFrame::Iterate(ObjectVisitor* v) const {
1334 StackHandlerIterator it(this, top_handler());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001335 DCHECK(!it.done());
Steve Blocka7e24c12009-10-30 11:49:00 +00001336 StackHandler* handler = it.handler();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001337 DCHECK(handler->is_js_entry());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001338 handler->Iterate(v, LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001339#ifdef DEBUG
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001340 // Make sure that the entry frame does not contain more than one
1341 // stack handler.
Steve Blocka7e24c12009-10-30 11:49:00 +00001342 it.Advance();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001343 DCHECK(it.done());
Steve Blocka7e24c12009-10-30 11:49:00 +00001344#endif
Ben Murdoch8b112d22011-06-08 16:22:53 +01001345 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001346}
1347
1348
1349void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001350 const int offset = StandardFrameConstants::kLastObjectOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +00001351 Object** base = &Memory::Object_at(sp());
1352 Object** limit = &Memory::Object_at(fp() + offset) + 1;
1353 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1354 StackHandler* handler = it.handler();
1355 // Traverse pointers down to - but not including - the next
1356 // handler in the handler chain. Update the base to skip the
1357 // handler and allow the handler to traverse its own pointers.
1358 const Address address = handler->address();
1359 v->VisitPointers(base, reinterpret_cast<Object**>(address));
1360 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1361 // Traverse the pointers in the handler itself.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001362 handler->Iterate(v, LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001363 }
1364 v->VisitPointers(base, limit);
1365}
1366
1367
1368void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1369 IterateExpressions(v);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001370 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001371}
1372
1373
1374void InternalFrame::Iterate(ObjectVisitor* v) const {
1375 // Internal frames only have object pointers on the expression stack
1376 // as they never have any arguments.
1377 IterateExpressions(v);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001378 IteratePc(v, pc_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001379}
1380
1381
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001382void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
1383 Object** base = &Memory::Object_at(sp());
1384 Object** limit = &Memory::Object_at(fp() +
1385 kFirstRegisterParameterFrameOffset);
1386 v->VisitPointers(base, limit);
1387 base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset);
1388 const int offset = StandardFrameConstants::kLastObjectOffset;
1389 limit = &Memory::Object_at(fp() + offset) + 1;
1390 v->VisitPointers(base, limit);
1391 IteratePc(v, pc_address(), LookupCode());
1392}
1393
1394
1395Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
1396 return fp() + StandardFrameConstants::kCallerSPOffset;
1397}
1398
1399
1400Code* StubFailureTrampolineFrame::unchecked_code() const {
1401 Code* trampoline;
1402 StubFailureTrampolineStub(isolate(), NOT_JS_FUNCTION_STUB_MODE).
1403 FindCodeInCache(&trampoline);
1404 if (trampoline->contains(pc())) {
1405 return trampoline;
1406 }
1407
1408 StubFailureTrampolineStub(isolate(), JS_FUNCTION_STUB_MODE).
1409 FindCodeInCache(&trampoline);
1410 if (trampoline->contains(pc())) {
1411 return trampoline;
1412 }
1413
1414 UNREACHABLE();
1415 return NULL;
1416}
1417
1418
Steve Blocka7e24c12009-10-30 11:49:00 +00001419// -------------------------------------------------------------------------
1420
1421
1422JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001423 DCHECK(n >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001424 for (int i = 0; i <= n; i++) {
1425 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1426 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1427 iterator_.Advance();
1428 }
1429 UNREACHABLE();
1430 return NULL;
1431}
1432
1433
1434// -------------------------------------------------------------------------
1435
1436
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001437static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1438 MapWord map_word = object->map_word();
1439 return map_word.IsForwardingAddress() ?
1440 map_word.ToForwardingAddress()->map() : map_word.ToMap();
1441}
1442
1443
1444static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1445 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1446}
1447
1448
1449#ifdef DEBUG
1450static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1451 Map* map = GcSafeMapOfCodeSpaceObject(code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001452 DCHECK(map == code->GetHeap()->code_map());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001453 Address start = code->address();
1454 Address end = code->address() + code->SizeFromMap(map);
1455 return start <= addr && addr < end;
1456}
1457#endif
1458
1459
1460Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1461 Address inner_pointer) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001462 Code* code = reinterpret_cast<Code*>(object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001463 DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001464 return code;
1465}
1466
1467
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001468Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1469 Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001470 Heap* heap = isolate_->heap();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001471 // Check if the inner pointer points into a large object chunk.
1472 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1473 if (large_page != NULL) {
1474 return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1475 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001476
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001477 // Iterate through the page until we reach the end or find an object starting
1478 // after the inner pointer.
1479 Page* page = Page::FromAddress(inner_pointer);
1480
1481 Address addr = page->skip_list()->StartFor(inner_pointer);
1482
1483 Address top = heap->code_space()->top();
1484 Address limit = heap->code_space()->limit();
1485
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001486 while (true) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001487 if (addr == top && addr != limit) {
1488 addr = limit;
1489 continue;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001490 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001491
1492 HeapObject* obj = HeapObject::FromAddress(addr);
1493 int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1494 Address next_addr = addr + obj_size;
1495 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1496 addr = next_addr;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001497 }
1498}
1499
Ben Murdochb0fe1622011-05-05 13:52:32 +01001500
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001501InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1502 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001503 isolate_->counters()->pc_to_code()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001504 DCHECK(base::bits::IsPowerOfTwo32(kInnerPointerToCodeCacheSize));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001505 uint32_t hash = ComputeIntegerHash(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001506 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)),
Ben Murdochc7cc0282012-03-05 14:35:55 +00001507 v8::internal::kZeroHashSeed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001508 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1509 InnerPointerToCodeCacheEntry* entry = cache(index);
1510 if (entry->inner_pointer == inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001511 isolate_->counters()->pc_to_code_cached()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001512 DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001513 } else {
1514 // Because this code may be interrupted by a profiling signal that
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001515 // also queries the cache, we cannot update inner_pointer before the code
1516 // has been set. Otherwise, we risk trying to use a cache entry before
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001517 // the code has been computed.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001518 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001519 entry->safepoint_entry.Reset();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001520 entry->inner_pointer = inner_pointer;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001521 }
1522 return entry;
1523}
1524
1525
1526// -------------------------------------------------------------------------
1527
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001528
1529void StackHandler::Unwind(Isolate* isolate,
1530 FixedArray* array,
1531 int offset,
1532 int previous_handler_offset) const {
1533 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5);
1534 DCHECK_LE(0, offset);
1535 DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount);
1536 // Unwinding a stack handler into an array chains it in the opposite
1537 // direction, re-using the "next" slot as a "previous" link, so that stack
1538 // handlers can be later re-wound in the correct order. Decode the "state"
1539 // slot into "index" and "kind" and store them separately, using the fp slot.
1540 array->set(offset, Smi::FromInt(previous_handler_offset)); // next
1541 array->set(offset + 1, *code_address()); // code
1542 array->set(offset + 2, Smi::FromInt(static_cast<int>(index()))); // state
1543 array->set(offset + 3, *context_address()); // context
1544 array->set(offset + 4, Smi::FromInt(static_cast<int>(kind()))); // fp
1545
1546 *isolate->handler_address() = next()->address();
Steve Blocka7e24c12009-10-30 11:49:00 +00001547}
1548
1549
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001550int StackHandler::Rewind(Isolate* isolate,
1551 FixedArray* array,
1552 int offset,
1553 Address fp) {
1554 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5);
1555 DCHECK_LE(0, offset);
1556 DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount);
1557 Smi* prev_handler_offset = Smi::cast(array->get(offset));
1558 Code* code = Code::cast(array->get(offset + 1));
1559 Smi* smi_index = Smi::cast(array->get(offset + 2));
1560 Object* context = array->get(offset + 3);
1561 Smi* smi_kind = Smi::cast(array->get(offset + 4));
Steve Blocka7e24c12009-10-30 11:49:00 +00001562
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001563 unsigned state = KindField::encode(static_cast<Kind>(smi_kind->value())) |
1564 IndexField::encode(static_cast<unsigned>(smi_index->value()));
1565
1566 Memory::Address_at(address() + StackHandlerConstants::kNextOffset) =
1567 *isolate->handler_address();
1568 Memory::Object_at(address() + StackHandlerConstants::kCodeOffset) = code;
1569 Memory::uintptr_at(address() + StackHandlerConstants::kStateOffset) = state;
1570 Memory::Object_at(address() + StackHandlerConstants::kContextOffset) =
1571 context;
1572 SetFp(address() + StackHandlerConstants::kFPOffset, fp);
1573
1574 *isolate->handler_address() = address();
1575
1576 return prev_handler_offset->value();
1577}
1578
1579
1580// -------------------------------------------------------------------------
1581
1582int NumRegs(RegList reglist) { return base::bits::CountPopulation32(reglist); }
1583
1584
1585struct JSCallerSavedCodeData {
Steve Block44f0eee2011-05-26 01:26:41 +01001586 int reg_code[kNumJSCallerSaved];
1587};
1588
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001589JSCallerSavedCodeData caller_saved_code_data;
Steve Block44f0eee2011-05-26 01:26:41 +01001590
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001591void SetUpJSCallerSavedCodeData() {
1592 int i = 0;
1593 for (int r = 0; r < kNumRegs; r++)
1594 if ((kJSCallerSaved & (1 << r)) != 0)
1595 caller_saved_code_data.reg_code[i++] = r;
1596
1597 DCHECK(i == kNumJSCallerSaved);
1598}
1599
Steve Block44f0eee2011-05-26 01:26:41 +01001600
1601int JSCallerSavedCode(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001602 DCHECK(0 <= n && n < kNumJSCallerSaved);
1603 return caller_saved_code_data.reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001604}
1605
1606
Steve Block6ded16b2010-05-10 14:33:55 +01001607#define DEFINE_WRAPPER(type, field) \
1608class field##_Wrapper : public ZoneObject { \
1609 public: /* NOLINT */ \
1610 field##_Wrapper(const field& original) : frame_(original) { \
1611 } \
1612 field frame_; \
1613};
1614STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1615#undef DEFINE_WRAPPER
1616
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
Steve Block6ded16b2010-05-10 14:33:55 +01001618#define FRAME_TYPE_CASE(type, field) \
1619 case StackFrame::type: { \
1620 field##_Wrapper* wrapper = \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001621 new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
Steve Block6ded16b2010-05-10 14:33:55 +01001622 return &wrapper->frame_; \
1623 }
1624
1625 switch (frame->type()) {
1626 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1627 default: UNREACHABLE();
1628 }
1629#undef FRAME_TYPE_CASE
1630 return NULL;
1631}
1632
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001633
1634Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
1635 ZoneList<StackFrame*> list(10, zone);
1636 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1637 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1638 list.Add(frame, zone);
Steve Block6ded16b2010-05-10 14:33:55 +01001639 }
1640 return list.ToVector();
1641}
1642
1643
Steve Blocka7e24c12009-10-30 11:49:00 +00001644} } // namespace v8::internal