blob: ed407e796b637af4072e6be69b85c8cd64fe86c0 [file] [log] [blame]
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
kasperl@chromium.orga5551262010-12-07 12:49:48 +000030#include "ast.h"
31#include "deoptimizer.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000032#include "frames-inl.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000033#include "full-codegen.h"
jkummerow@chromium.org1456e702012-03-30 08:38:13 +000034#include "lazy-instance.h"
kasperl@chromium.org061ef742009-02-27 12:16:20 +000035#include "mark-compact.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000036#include "safepoint-table.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037#include "scopeinfo.h"
38#include "string-stream.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039
whesse@chromium.org030d38e2011-07-13 13:23:34 +000040#include "allocation-inl.h"
41
kasperl@chromium.org71affb52009-05-26 05:44:31 +000042namespace v8 {
43namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000044
ulan@chromium.org967e2702012-02-28 09:49:15 +000045
46static ReturnAddressLocationResolver return_address_location_resolver = NULL;
47
48
49// Resolves pc_address through the resolution address function if one is set.
50static inline Address* ResolveReturnAddressLocation(Address* pc_address) {
51 if (return_address_location_resolver == NULL) {
52 return pc_address;
53 } else {
54 return reinterpret_cast<Address*>(
55 return_address_location_resolver(
56 reinterpret_cast<uintptr_t>(pc_address)));
57 }
58}
59
60
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000061// Iterator that supports traversing the stack handlers of a
62// particular frame. Needs to know the top of the handler chain.
63class StackHandlerIterator BASE_EMBEDDED {
64 public:
65 StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
66 : limit_(frame->fp()), handler_(handler) {
67 // Make sure the handler has already been unwound to this frame.
68 ASSERT(frame->sp() <= handler->address());
69 }
70
71 StackHandler* handler() const { return handler_; }
72
ager@chromium.orgeadaf222009-06-16 09:43:10 +000073 bool done() {
74 return handler_ == NULL || handler_->address() > limit_;
75 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000076 void Advance() {
77 ASSERT(!done());
78 handler_ = handler_->next();
79 }
80
81 private:
82 const Address limit_;
83 StackHandler* handler_;
84};
85
86
87// -------------------------------------------------------------------------
88
89
90#define INITIALIZE_SINGLETON(type, field) field##_(this),
vegorov@chromium.org74f333b2011-04-06 11:17:46 +000091StackFrameIterator::StackFrameIterator(Isolate* isolate)
92 : isolate_(isolate),
93 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
94 frame_(NULL), handler_(NULL),
95 thread_(isolate_->thread_local_top()),
96 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
97 Reset();
98}
99StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
100 : isolate_(isolate),
101 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000102 frame_(NULL), handler_(NULL), thread_(t),
103 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000104 Reset();
105}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000106StackFrameIterator::StackFrameIterator(Isolate* isolate,
107 bool use_top, Address fp, Address sp)
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000108 : isolate_(isolate),
109 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000110 frame_(NULL), handler_(NULL),
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000111 thread_(use_top ? isolate_->thread_local_top() : NULL),
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000112 fp_(use_top ? NULL : fp), sp_(sp),
113 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
114 &StackFrameIterator::AdvanceWithoutHandler) {
115 if (use_top || fp != NULL) {
116 Reset();
117 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000118}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000119
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000120#undef INITIALIZE_SINGLETON
121
122
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000123void StackFrameIterator::AdvanceWithHandler() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124 ASSERT(!done());
125 // Compute the state of the calling frame before restoring
126 // callee-saved registers and unwinding handlers. This allows the
127 // frame code that computes the caller state to access the top
128 // handler and the value of any callee-saved register if needed.
129 StackFrame::State state;
130 StackFrame::Type type = frame_->GetCallerState(&state);
131
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000132 // Unwind handlers corresponding to the current frame.
133 StackHandlerIterator it(frame_, handler_);
134 while (!it.done()) it.Advance();
135 handler_ = it.handler();
136
137 // Advance to the calling frame.
138 frame_ = SingletonFor(type, &state);
139
140 // When we're done iterating over the stack frames, the handler
141 // chain must have been completely unwound.
142 ASSERT(!done() || handler_ == NULL);
143}
144
145
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000146void StackFrameIterator::AdvanceWithoutHandler() {
147 // A simpler version of Advance which doesn't care about handler.
148 ASSERT(!done());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000149 StackFrame::State state;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000150 StackFrame::Type type = frame_->GetCallerState(&state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000151 frame_ = SingletonFor(type, &state);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000152}
153
154
155void StackFrameIterator::Reset() {
156 StackFrame::State state;
157 StackFrame::Type type;
158 if (thread_ != NULL) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000159 type = ExitFrame::GetStateForFramePointer(
160 Isolate::c_entry_fp(thread_), &state);
161 handler_ = StackHandler::FromAddress(
162 Isolate::handler(thread_));
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000163 } else {
164 ASSERT(fp_ != NULL);
165 state.fp = fp_;
166 state.sp = sp_;
ulan@chromium.org967e2702012-02-28 09:49:15 +0000167 state.pc_address = ResolveReturnAddressLocation(
168 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)));
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000169 type = StackFrame::ComputeType(isolate(), &state);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000170 }
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000171 if (SingletonFor(type) == NULL) return;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000172 frame_ = SingletonFor(type, &state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000173}
174
175
176StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
177 StackFrame::State* state) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000178 if (type == StackFrame::NONE) return NULL;
179 StackFrame* result = SingletonFor(type);
180 ASSERT(result != NULL);
181 result->state_ = *state;
182 return result;
183}
184
185
186StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000187#define FRAME_TYPE_CASE(type, field) \
188 case StackFrame::type: result = &field##_; break;
189
190 StackFrame* result = NULL;
191 switch (type) {
192 case StackFrame::NONE: return NULL;
193 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
194 default: break;
195 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196 return result;
197
198#undef FRAME_TYPE_CASE
199}
200
201
202// -------------------------------------------------------------------------
203
204
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000205StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
206 : JavaScriptFrameIterator(isolate) {
207 if (!done() && !IsValidFrame()) Advance();
208}
209
210
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000211void StackTraceFrameIterator::Advance() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212 while (true) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000213 JavaScriptFrameIterator::Advance();
214 if (done()) return;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000215 if (IsValidFrame()) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216 }
217}
218
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000219bool StackTraceFrameIterator::IsValidFrame() {
220 if (!frame()->function()->IsJSFunction()) return false;
221 Object* script = JSFunction::cast(frame()->function())->shared()->script();
222 // Don't show functions from native scripts to user.
223 return (script->IsScript() &&
224 Script::TYPE_NATIVE != Script::cast(script)->type()->value());
225}
226
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000227
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000228// -------------------------------------------------------------------------
229
230
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000231bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
232 if (!validator_.IsValid(fp)) return false;
233 Address sp = ExitFrame::ComputeStackPointer(fp);
234 if (!validator_.IsValid(sp)) return false;
235 StackFrame::State state;
236 ExitFrame::FillState(fp, sp, &state);
237 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
238 return false;
239 }
240 return *state.pc_address != NULL;
241}
242
243
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000244SafeStackFrameIterator::ActiveCountMaintainer::ActiveCountMaintainer(
245 Isolate* isolate)
246 : isolate_(isolate) {
247 isolate_->set_safe_stack_iterator_counter(
248 isolate_->safe_stack_iterator_counter() + 1);
249}
250
251
252SafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() {
253 isolate_->set_safe_stack_iterator_counter(
254 isolate_->safe_stack_iterator_counter() - 1);
255}
256
257
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000258SafeStackFrameIterator::SafeStackFrameIterator(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000259 Isolate* isolate,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000260 Address fp, Address sp, Address low_bound, Address high_bound) :
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000261 maintainer_(isolate),
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000262 stack_validator_(low_bound, high_bound),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000263 is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000264 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
265 is_working_iterator_(is_valid_top_ || is_valid_fp_),
266 iteration_done_(!is_working_iterator_),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000267 iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000268}
269
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000270bool SafeStackFrameIterator::is_active(Isolate* isolate) {
271 return isolate->safe_stack_iterator_counter() > 0;
272}
273
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000274
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000275bool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
276 Address low_bound, Address high_bound) {
277 ThreadLocalTop* top = isolate->thread_local_top();
278 Address fp = Isolate::c_entry_fp(top);
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000279 ExitFrameValidator validator(low_bound, high_bound);
280 if (!validator.IsValidFP(fp)) return false;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000281 return Isolate::handler(top) != NULL;
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000282}
283
284
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000285void SafeStackFrameIterator::Advance() {
286 ASSERT(is_working_iterator_);
287 ASSERT(!done());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000288 StackFrame* last_frame = iterator_.frame();
289 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
290 // Before advancing to the next stack frame, perform pointer validity tests
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000291 iteration_done_ = !IsValidFrame(last_frame) ||
292 !CanIterateHandles(last_frame, iterator_.handler()) ||
293 !IsValidCaller(last_frame);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000294 if (iteration_done_) return;
295
296 iterator_.Advance();
297 if (iterator_.done()) return;
298 // Check that we have actually moved to the previous frame in the stack
299 StackFrame* prev_frame = iterator_.frame();
300 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
301}
302
303
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000304bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
305 StackHandler* handler) {
306 // If StackIterator iterates over StackHandles, verify that
307 // StackHandlerIterator can be instantiated (see StackHandlerIterator
308 // constructor.)
309 return !is_valid_top_ || (frame->sp() <= handler->address());
310}
311
312
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000313bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000314 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000315}
316
317
318bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
319 StackFrame::State state;
ager@chromium.org41826e72009-03-30 13:30:57 +0000320 if (frame->is_entry() || frame->is_entry_construct()) {
321 // See EntryFrame::GetCallerState. It computes the caller FP address
322 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
323 // sure that caller FP address is valid.
324 Address caller_fp = Memory::Address_at(
325 frame->fp() + EntryFrameConstants::kCallerFPOffset);
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000326 ExitFrameValidator validator(stack_validator_);
327 if (!validator.IsValidFP(caller_fp)) return false;
ager@chromium.org41826e72009-03-30 13:30:57 +0000328 } else if (frame->is_arguments_adaptor()) {
329 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
330 // the number of arguments is stored on stack as Smi. We need to check
331 // that it really an Smi.
332 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
333 GetExpression(0);
334 if (!number_of_args->IsSmi()) {
335 return false;
336 }
337 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000338 frame->ComputeCallerState(&state);
339 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
340 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000341}
342
343
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000344void SafeStackFrameIterator::Reset() {
345 if (is_working_iterator_) {
346 iterator_.Reset();
347 iteration_done_ = false;
348 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000349}
350
351
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000352// -------------------------------------------------------------------------
353
354
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000355SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000356 Isolate* isolate,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000357 Address fp, Address sp, Address low_bound, Address high_bound) :
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000358 SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) {
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000359 if (!done() && !frame()->is_java_script()) Advance();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000360}
361
362
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000363void SafeStackTraceFrameIterator::Advance() {
364 while (true) {
365 SafeJavaScriptFrameIterator::Advance();
366 if (done()) return;
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000367 if (frame()->is_java_script()) return;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000368 }
369}
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000370
371
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000372Code* StackFrame::GetSafepointData(Isolate* isolate,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000373 Address inner_pointer,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000374 SafepointEntry* safepoint_entry,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000375 unsigned* stack_slots) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000376 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
377 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000378 if (!entry->safepoint_entry.is_valid()) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000379 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000380 ASSERT(entry->safepoint_entry.is_valid());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000381 } else {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000382 ASSERT(entry->safepoint_entry.Equals(
383 entry->code->GetSafepointEntry(inner_pointer)));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000384 }
385
386 // Fill in the results and return the code.
387 Code* code = entry->code;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000388 *safepoint_entry = entry->safepoint_entry;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000389 *stack_slots = code->stack_slots();
390 return code;
391}
392
393
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000394bool StackFrame::HasHandler() const {
395 StackHandlerIterator it(this, top_handler());
396 return !it.done();
397}
398
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000399
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000400#ifdef DEBUG
401static bool GcSafeCodeContains(HeapObject* object, Address addr);
402#endif
403
404
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000405void StackFrame::IteratePc(ObjectVisitor* v,
406 Address* pc_address,
407 Code* holder) {
408 Address pc = *pc_address;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000409 ASSERT(GcSafeCodeContains(holder, pc));
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000410 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
411 Object* code = holder;
412 v->VisitPointer(&code);
413 if (code != holder) {
414 holder = reinterpret_cast<Code*>(code);
415 pc = holder->instruction_start() + pc_offset;
416 *pc_address = pc;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000417 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000418}
419
420
ulan@chromium.org967e2702012-02-28 09:49:15 +0000421void StackFrame::SetReturnAddressLocationResolver(
422 ReturnAddressLocationResolver resolver) {
423 ASSERT(return_address_location_resolver == NULL);
424 return_address_location_resolver = resolver;
425}
426
427
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000428StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000429 ASSERT(state->fp != NULL);
430 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
431 return ARGUMENTS_ADAPTOR;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000433 // The marker and function offsets overlap. If the marker isn't a
434 // smi then the frame is a JavaScript frame -- and the marker is
435 // really the function.
436 const int offset = StandardFrameConstants::kMarkerOffset;
437 Object* marker = Memory::Object_at(state->fp + offset);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000438 if (!marker->IsSmi()) {
439 // If we're using a "safe" stack iterator, we treat optimized
440 // frames as normal JavaScript frames to avoid having to look
441 // into the heap to determine the state. This is safe as long
442 // as nobody tries to GC...
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000443 if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT;
444 Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000445 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
446 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
447 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000448 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000449}
450
451
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000452
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000453StackFrame::Type StackFrame::GetCallerState(State* state) const {
454 ComputeCallerState(state);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000455 return ComputeType(isolate(), state);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000456}
457
458
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000459Address StackFrame::UnpaddedFP() const {
460#if defined(V8_TARGET_ARCH_IA32)
461 if (!is_optimized()) return fp();
462 int32_t alignment_state = Memory::int32_at(
463 fp() + JavaScriptFrameConstants::kDynamicAlignmentStateOffset);
464
465 return (alignment_state == kAlignmentPaddingPushed) ?
466 (fp() + kPointerSize) : fp();
467#else
468 return fp();
469#endif
470}
471
472
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000473Code* EntryFrame::unchecked_code() const {
danno@chromium.org72204d52012-10-31 10:02:10 +0000474 return HEAP->js_entry_code();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000475}
476
477
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000478void EntryFrame::ComputeCallerState(State* state) const {
479 GetCallerState(state);
480}
481
482
ager@chromium.org357bf652010-04-12 11:30:10 +0000483void EntryFrame::SetCallerFp(Address caller_fp) {
484 const int offset = EntryFrameConstants::kCallerFPOffset;
485 Memory::Address_at(this->fp() + offset) = caller_fp;
486}
487
488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000489StackFrame::Type EntryFrame::GetCallerState(State* state) const {
490 const int offset = EntryFrameConstants::kCallerFPOffset;
491 Address fp = Memory::Address_at(this->fp() + offset);
492 return ExitFrame::GetStateForFramePointer(fp, state);
493}
494
495
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000496Code* EntryConstructFrame::unchecked_code() const {
danno@chromium.org72204d52012-10-31 10:02:10 +0000497 return HEAP->js_construct_entry_code();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000498}
499
500
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000501Object*& ExitFrame::code_slot() const {
502 const int offset = ExitFrameConstants::kCodeOffset;
503 return Memory::Object_at(fp() + offset);
504}
505
506
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000507Code* ExitFrame::unchecked_code() const {
508 return reinterpret_cast<Code*>(code_slot());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000509}
510
511
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000512void ExitFrame::ComputeCallerState(State* state) const {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000513 // Set up the caller state.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000514 state->sp = caller_sp();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
ulan@chromium.org967e2702012-02-28 09:49:15 +0000516 state->pc_address = ResolveReturnAddressLocation(
517 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518}
519
520
ager@chromium.org357bf652010-04-12 11:30:10 +0000521void ExitFrame::SetCallerFp(Address caller_fp) {
522 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
523}
524
525
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000526void ExitFrame::Iterate(ObjectVisitor* v) const {
527 // The arguments are traversed as part of the expression stack of
528 // the calling frame.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000529 IteratePc(v, pc_address(), LookupCode());
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000530 v->VisitPointer(&code_slot());
531}
532
533
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000534Address ExitFrame::GetCallerStackPointer() const {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000535 return fp() + ExitFrameConstants::kCallerSPDisplacement;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000536}
537
538
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000539StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
540 if (fp == 0) return NONE;
541 Address sp = ComputeStackPointer(fp);
542 FillState(fp, sp, state);
543 ASSERT(*state->pc_address != NULL);
544 return EXIT;
545}
546
547
548void ExitFrame::FillState(Address fp, Address sp, State* state) {
549 state->sp = sp;
550 state->fp = fp;
ulan@chromium.org967e2702012-02-28 09:49:15 +0000551 state->pc_address = ResolveReturnAddressLocation(
552 reinterpret_cast<Address*>(sp - 1 * kPointerSize));
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000553}
554
555
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000556Address StandardFrame::GetExpressionAddress(int n) const {
kasper.lund7276f142008-07-30 08:49:36 +0000557 const int offset = StandardFrameConstants::kExpressionsOffset;
558 return fp() + offset - n * kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000559}
560
561
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000562Object* StandardFrame::GetExpression(Address fp, int index) {
563 return Memory::Object_at(GetExpressionAddress(fp, index));
564}
565
566
567Address StandardFrame::GetExpressionAddress(Address fp, int n) {
568 const int offset = StandardFrameConstants::kExpressionsOffset;
569 return fp + offset - n * kPointerSize;
570}
571
572
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000573int StandardFrame::ComputeExpressionsCount() const {
574 const int offset =
575 StandardFrameConstants::kExpressionsOffset + kPointerSize;
576 Address base = fp() + offset;
577 Address limit = sp();
578 ASSERT(base >= limit); // stack grows downwards
579 // Include register-allocated locals in number of expressions.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000580 return static_cast<int>((base - limit) / kPointerSize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000581}
582
583
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000584void StandardFrame::ComputeCallerState(State* state) const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000585 state->sp = caller_sp();
586 state->fp = caller_fp();
ulan@chromium.org967e2702012-02-28 09:49:15 +0000587 state->pc_address = ResolveReturnAddressLocation(
588 reinterpret_cast<Address*>(ComputePCAddress(fp())));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000589}
590
591
ager@chromium.org357bf652010-04-12 11:30:10 +0000592void StandardFrame::SetCallerFp(Address caller_fp) {
593 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
594 caller_fp;
595}
596
597
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000598bool StandardFrame::IsExpressionInsideHandler(int n) const {
599 Address address = GetExpressionAddress(n);
600 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
601 if (it.handler()->includes(address)) return true;
602 }
603 return false;
604}
605
606
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000607void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000608 // Make sure that we're not doing "safe" stack frame iteration. We cannot
609 // possibly find pointers in optimized frames in that state.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000610 ASSERT(!SafeStackFrameIterator::is_active(isolate()));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000611
612 // Compute the safepoint information.
613 unsigned stack_slots = 0;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000614 SafepointEntry safepoint_entry;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000615 Code* code = StackFrame::GetSafepointData(
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000616 isolate(), pc(), &safepoint_entry, &stack_slots);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000617 unsigned slot_space = stack_slots * kPointerSize;
618
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000619 // Visit the outgoing parameters.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000620 Object** parameters_base = &Memory::Object_at(sp());
621 Object** parameters_limit = &Memory::Object_at(
622 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
623
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000624 // Visit the parameters that may be on top of the saved registers.
625 if (safepoint_entry.argument_count() > 0) {
626 v->VisitPointers(parameters_base,
627 parameters_base + safepoint_entry.argument_count());
628 parameters_base += safepoint_entry.argument_count();
629 }
630
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000631 // Skip saved double registers.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000632 if (safepoint_entry.has_doubles()) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000633 // Number of doubles not known at snapshot time.
634 ASSERT(!Serializer::enabled());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000635 parameters_base += DoubleRegister::NumAllocatableRegisters() *
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000636 kDoubleSize / kPointerSize;
637 }
638
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000639 // Visit the registers that contain pointers if any.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000640 if (safepoint_entry.HasRegisters()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000641 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000642 if (safepoint_entry.HasRegisterAt(i)) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000643 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
644 v->VisitPointer(parameters_base + reg_stack_index);
645 }
646 }
647 // Skip the words containing the register values.
648 parameters_base += kNumSafepointRegisters;
649 }
650
651 // We're done dealing with the register bits.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000652 uint8_t* safepoint_bits = safepoint_entry.bits();
653 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000654
655 // Visit the rest of the parameters.
656 v->VisitPointers(parameters_base, parameters_limit);
657
658 // Visit pointer spill slots and locals.
659 for (unsigned index = 0; index < stack_slots; index++) {
660 int byte_index = index >> kBitsPerByteLog2;
661 int bit_index = index & (kBitsPerByte - 1);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000662 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000663 v->VisitPointer(parameters_limit + index);
664 }
665 }
666
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000667 // Visit the return address in the callee and incoming arguments.
668 IteratePc(v, pc_address(), code);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000669
670 // Visit the context in stub frame and JavaScript frame.
671 // Visit the function in JavaScript frame.
672 Object** fixed_base = &Memory::Object_at(
673 fp() + StandardFrameConstants::kMarkerOffset);
674 Object** fixed_limit = &Memory::Object_at(fp());
675 v->VisitPointers(fixed_base, fixed_limit);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000676}
677
678
679void StubFrame::Iterate(ObjectVisitor* v) const {
680 IterateCompiledFrame(v);
681}
682
683
684Code* StubFrame::unchecked_code() const {
685 return static_cast<Code*>(isolate()->heap()->FindCodeObject(pc()));
686}
687
688
689Address StubFrame::GetCallerStackPointer() const {
690 return fp() + ExitFrameConstants::kCallerSPDisplacement;
691}
692
693
694int StubFrame::GetNumberOfIncomingArguments() const {
695 return 0;
696}
697
698
699void OptimizedFrame::Iterate(ObjectVisitor* v) const {
700#ifdef DEBUG
701 // Make sure that optimized frames do not contain any stack handlers.
702 StackHandlerIterator it(this, top_handler());
703 ASSERT(it.done());
704#endif
705
706 IterateCompiledFrame(v);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000707}
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +0000708
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000709
710void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
711 Memory::Object_at(GetParameterSlot(index)) = value;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000712}
713
714
715bool JavaScriptFrame::IsConstructor() const {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000716 Address fp = caller_fp();
717 if (has_adapted_arguments()) {
718 // Skip the arguments adaptor frame and look at the real caller.
719 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
720 }
721 return IsConstructFrame(fp);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000722}
723
724
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000725int JavaScriptFrame::GetArgumentsLength() const {
726 // If there is an arguments adaptor frame get the arguments length from it.
727 if (has_adapted_arguments()) {
728 return Smi::cast(GetExpression(caller_fp(), 0))->value();
729 } else {
730 return GetNumberOfIncomingArguments();
731 }
732}
733
734
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000735Code* JavaScriptFrame::unchecked_code() const {
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000736 JSFunction* function = JSFunction::cast(this->function());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000737 return function->unchecked_code();
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000738}
739
740
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000741int JavaScriptFrame::GetNumberOfIncomingArguments() const {
742 ASSERT(!SafeStackFrameIterator::is_active(isolate()) &&
743 isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
744
745 JSFunction* function = JSFunction::cast(this->function());
746 return function->shared()->formal_parameter_count();
747}
748
749
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000750Address JavaScriptFrame::GetCallerStackPointer() const {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000751 return fp() + StandardFrameConstants::kCallerSPOffset;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000752}
753
754
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000755void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
756 ASSERT(functions->length() == 0);
757 functions->Add(JSFunction::cast(function()));
758}
759
760
761void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
762 ASSERT(functions->length() == 0);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000763 Code* code_pointer = LookupCode();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000764 int offset = static_cast<int>(pc() - code_pointer->address());
765 FrameSummary summary(receiver(),
766 JSFunction::cast(function()),
767 code_pointer,
768 offset,
769 IsConstructor());
770 functions->Add(summary);
771}
772
773
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000774void JavaScriptFrame::PrintTop(Isolate* isolate,
775 FILE* file,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000776 bool print_args,
777 bool print_line_number) {
778 // constructor calls
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000779 HandleScope scope(isolate);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000780 AssertNoAllocation no_allocation;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000781 JavaScriptFrameIterator it(isolate);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000782 while (!it.done()) {
783 if (it.frame()->is_java_script()) {
784 JavaScriptFrame* frame = it.frame();
785 if (frame->IsConstructor()) PrintF(file, "new ");
786 // function name
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000787 Object* maybe_fun = frame->function();
788 if (maybe_fun->IsJSFunction()) {
789 JSFunction* fun = JSFunction::cast(maybe_fun);
790 fun->PrintName();
791 Code* js_code = frame->unchecked_code();
792 Address pc = frame->pc();
793 int code_offset =
794 static_cast<int>(pc - js_code->instruction_start());
795 PrintF("+%d", code_offset);
796 SharedFunctionInfo* shared = fun->shared();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000797 if (print_line_number) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000798 Code* code = Code::cast(
799 v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
800 int source_pos = code->SourcePosition(pc);
801 Object* maybe_script = shared->script();
802 if (maybe_script->IsScript()) {
803 Handle<Script> script(Script::cast(maybe_script));
804 int line = GetScriptLineNumberSafe(script, source_pos) + 1;
805 Object* script_name_raw = script->name();
806 if (script_name_raw->IsString()) {
807 String* script_name = String::cast(script->name());
808 SmartArrayPointer<char> c_script_name =
809 script_name->ToCString(DISALLOW_NULLS,
810 ROBUST_STRING_TRAVERSAL);
811 PrintF(file, " at %s:%d", *c_script_name, line);
812 } else {
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000813 PrintF(file, " at <unknown>:%d", line);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000814 }
815 } else {
816 PrintF(file, " at <unknown>:<unknown>");
817 }
818 }
819 } else {
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000820 PrintF("<unknown>");
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000821 }
822
823 if (print_args) {
824 // function arguments
825 // (we are intentionally only printing the actually
826 // supplied parameters, not all parameters required)
827 PrintF(file, "(this=");
828 frame->receiver()->ShortPrint(file);
829 const int length = frame->ComputeParametersCount();
830 for (int i = 0; i < length; i++) {
831 PrintF(file, ", ");
832 frame->GetParameter(i)->ShortPrint(file);
833 }
834 PrintF(file, ")");
835 }
836 break;
837 }
838 it.Advance();
839 }
840}
841
842
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000843void FrameSummary::Print() {
844 PrintF("receiver: ");
845 receiver_->ShortPrint();
846 PrintF("\nfunction: ");
847 function_->shared()->DebugName()->ShortPrint();
848 PrintF("\ncode: ");
849 code_->ShortPrint();
850 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
851 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
852 PrintF("\npc: %d\n", offset_);
853}
854
855
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000856JSFunction* OptimizedFrame::LiteralAt(FixedArray* literal_array,
857 int literal_id) {
858 if (literal_id == Translation::kSelfLiteralId) {
859 return JSFunction::cast(function());
860 }
861
862 return JSFunction::cast(literal_array->get(literal_id));
863}
864
865
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000866void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
867 ASSERT(frames->length() == 0);
868 ASSERT(is_optimized());
869
ager@chromium.org378b34e2011-01-28 08:04:38 +0000870 int deopt_index = Safepoint::kNoDeoptimizationIndex;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000871 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000872 FixedArray* literal_array = data->LiteralArray();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000873
874 // BUG(3243555): Since we don't have a lazy-deopt registered at
875 // throw-statements, we can't use the translation at the call-site of
876 // throw. An entry with no deoptimization index indicates a call-site
877 // without a lazy-deopt. As a consequence we are not allowed to inline
878 // functions containing throw.
879 if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
880 JavaScriptFrame::Summarize(frames);
881 return;
882 }
883
884 TranslationIterator it(data->TranslationByteArray(),
885 data->TranslationIndex(deopt_index)->value());
886 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
887 ASSERT(opcode == Translation::BEGIN);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000888 it.Next(); // Drop frame count.
889 int jsframe_count = it.Next();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000890
891 // We create the summary in reverse order because the frames
892 // in the deoptimization translation are ordered bottom-to-top.
ulan@chromium.org967e2702012-02-28 09:49:15 +0000893 bool is_constructor = IsConstructor();
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000894 int i = jsframe_count;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000895 while (i > 0) {
896 opcode = static_cast<Translation::Opcode>(it.Next());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000897 if (opcode == Translation::JS_FRAME) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000898 i--;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000899 BailoutId ast_id = BailoutId(it.Next());
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000900 JSFunction* function = LiteralAt(literal_array, it.Next());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000901 it.Next(); // Skip height.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000902
903 // The translation commands are ordered and the receiver is always
904 // at the first position. Since we are always at a call when we need
905 // to construct a stack trace, the receiver is always in a stack slot.
906 opcode = static_cast<Translation::Opcode>(it.Next());
danno@chromium.org40cb8782011-05-25 07:58:50 +0000907 ASSERT(opcode == Translation::STACK_SLOT ||
908 opcode == Translation::LITERAL);
909 int index = it.Next();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000910
911 // Get the correct receiver in the optimized frame.
912 Object* receiver = NULL;
danno@chromium.org40cb8782011-05-25 07:58:50 +0000913 if (opcode == Translation::LITERAL) {
914 receiver = data->LiteralArray()->get(index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000915 } else {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000916 // Positive index means the value is spilled to the locals
917 // area. Negative means it is stored in the incoming parameter
918 // area.
919 if (index >= 0) {
920 receiver = GetExpression(index);
921 } else {
922 // Index -1 overlaps with last parameter, -n with the first parameter,
923 // (-n - 1) with the receiver with n being the number of parameters
924 // of the outermost, optimized frame.
925 int parameter_count = ComputeParametersCount();
926 int parameter_index = index + parameter_count;
927 receiver = (parameter_index == -1)
928 ? this->receiver()
929 : this->GetParameter(parameter_index);
930 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000931 }
932
933 Code* code = function->shared()->code();
934 DeoptimizationOutputData* output_data =
935 DeoptimizationOutputData::cast(code->deoptimization_data());
936 unsigned entry = Deoptimizer::GetOutputInfo(output_data,
937 ast_id,
938 function->shared());
939 unsigned pc_offset =
940 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
941 ASSERT(pc_offset > 0);
942
943 FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
944 frames->Add(summary);
ulan@chromium.org967e2702012-02-28 09:49:15 +0000945 is_constructor = false;
946 } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) {
947 // The next encountered JS_FRAME will be marked as a constructor call.
948 it.Skip(Translation::NumberOfOperandsFor(opcode));
949 ASSERT(!is_constructor);
950 is_constructor = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000951 } else {
952 // Skip over operands to advance to the next opcode.
953 it.Skip(Translation::NumberOfOperandsFor(opcode));
954 }
955 }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000956 ASSERT(!is_constructor);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000957}
958
959
960DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
961 int* deopt_index) {
962 ASSERT(is_optimized());
963
964 JSFunction* opt_function = JSFunction::cast(function());
965 Code* code = opt_function->code();
966
967 // The code object may have been replaced by lazy deoptimization. Fall
968 // back to a slow search in this case to find the original optimized
969 // code object.
970 if (!code->contains(pc())) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000971 code = isolate()->inner_pointer_to_code_cache()->
972 GcSafeFindCodeForInnerPointer(pc());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000973 }
974 ASSERT(code != NULL);
975 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
976
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000977 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
978 *deopt_index = safepoint_entry.deoptimization_index();
ager@chromium.org378b34e2011-01-28 08:04:38 +0000979 ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000980
981 return DeoptimizationInputData::cast(code->deoptimization_data());
982}
983
984
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000985int OptimizedFrame::GetInlineCount() {
986 ASSERT(is_optimized());
987
988 int deopt_index = Safepoint::kNoDeoptimizationIndex;
989 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
990
991 TranslationIterator it(data->TranslationByteArray(),
992 data->TranslationIndex(deopt_index)->value());
993 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
994 ASSERT(opcode == Translation::BEGIN);
995 USE(opcode);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000996 it.Next(); // Drop frame count.
997 int jsframe_count = it.Next();
998 return jsframe_count;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000999}
1000
1001
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001002void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
1003 ASSERT(functions->length() == 0);
1004 ASSERT(is_optimized());
1005
ager@chromium.org378b34e2011-01-28 08:04:38 +00001006 int deopt_index = Safepoint::kNoDeoptimizationIndex;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001007 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001008 FixedArray* literal_array = data->LiteralArray();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001009
1010 TranslationIterator it(data->TranslationByteArray(),
1011 data->TranslationIndex(deopt_index)->value());
1012 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
1013 ASSERT(opcode == Translation::BEGIN);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001014 it.Next(); // Drop frame count.
1015 int jsframe_count = it.Next();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001016
1017 // We insert the frames in reverse order because the frames
1018 // in the deoptimization translation are ordered bottom-to-top.
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001019 while (jsframe_count > 0) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001020 opcode = static_cast<Translation::Opcode>(it.Next());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001021 if (opcode == Translation::JS_FRAME) {
1022 jsframe_count--;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001023 it.Next(); // Skip ast id.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001024 JSFunction* function = LiteralAt(literal_array, it.Next());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001025 it.Next(); // Skip height.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001026 functions->Add(function);
1027 } else {
1028 // Skip over operands to advance to the next opcode.
1029 it.Skip(Translation::NumberOfOperandsFor(opcode));
1030 }
1031 }
1032}
1033
1034
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001035int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
1036 return Smi::cast(GetExpression(0))->value();
1037}
1038
1039
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001040Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001041 return fp() + StandardFrameConstants::kCallerSPOffset;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001042}
1043
1044
1045Address InternalFrame::GetCallerStackPointer() const {
1046 // Internal frames have no arguments. The stack pointer of the
1047 // caller is at a fixed offset from the frame pointer.
1048 return fp() + StandardFrameConstants::kCallerSPOffset;
1049}
1050
1051
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001052Code* ArgumentsAdaptorFrame::unchecked_code() const {
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001053 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001054 Builtins::kArgumentsAdaptorTrampoline);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001055}
1056
1057
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001058Code* InternalFrame::unchecked_code() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001059 const int offset = InternalFrameConstants::kCodeOffset;
1060 Object* code = Memory::Object_at(fp() + offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001061 ASSERT(code != NULL);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001062 return reinterpret_cast<Code*>(code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001063}
1064
1065
1066void StackFrame::PrintIndex(StringStream* accumulator,
1067 PrintMode mode,
1068 int index) {
1069 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1070}
1071
1072
1073void JavaScriptFrame::Print(StringStream* accumulator,
1074 PrintMode mode,
1075 int index) const {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001076 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001077 Object* receiver = this->receiver();
1078 Object* function = this->function();
1079
1080 accumulator->PrintSecurityTokenIfChanged(function);
1081 PrintIndex(accumulator, mode, index);
1082 Code* code = NULL;
1083 if (IsConstructor()) accumulator->Add("new ");
1084 accumulator->PrintFunction(function, receiver, &code);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001085
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001086 // Get scope information for nicer output, if possible. If code is NULL, or
1087 // doesn't contain scope info, scope_info will return 0 for the number of
1088 // parameters, stack local variables, context local variables, stack slots,
1089 // or context slots.
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001090 Handle<ScopeInfo> scope_info(ScopeInfo::Empty(isolate()));
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00001091
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001092 if (function->IsJSFunction()) {
1093 Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001094 scope_info = Handle<ScopeInfo>(shared->scope_info());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001095 Object* script_obj = shared->script();
1096 if (script_obj->IsScript()) {
1097 Handle<Script> script(Script::cast(script_obj));
1098 accumulator->Add(" [");
1099 accumulator->PrintName(script->name());
1100
1101 Address pc = this->pc();
1102 if (code != NULL && code->kind() == Code::FUNCTION &&
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +00001103 pc >= code->instruction_start() && pc < code->instruction_end()) {
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001104 int source_pos = code->SourcePosition(pc);
1105 int line = GetScriptLineNumberSafe(script, source_pos) + 1;
1106 accumulator->Add(":%d", line);
1107 } else {
1108 int function_start_pos = shared->start_position();
1109 int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
1110 accumulator->Add(":~%d", line);
1111 }
1112
1113 accumulator->Add("] ");
1114 }
1115 }
1116
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001117 accumulator->Add("(this=%o", receiver);
1118
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001119 // Print the parameters.
1120 int parameters_count = ComputeParametersCount();
1121 for (int i = 0; i < parameters_count; i++) {
1122 accumulator->Add(",");
1123 // If we have a name for the parameter we print it. Nameless
1124 // parameters are either because we have more actual parameters
1125 // than formal parameters or because we have no scope information.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001126 if (i < scope_info->ParameterCount()) {
1127 accumulator->PrintName(scope_info->ParameterName(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001128 accumulator->Add("=");
1129 }
1130 accumulator->Add("%o", GetParameter(i));
1131 }
1132
1133 accumulator->Add(")");
1134 if (mode == OVERVIEW) {
1135 accumulator->Add("\n");
1136 return;
1137 }
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001138 if (is_optimized()) {
1139 accumulator->Add(" {\n// optimized frame\n}\n");
1140 return;
1141 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001142 accumulator->Add(" {\n");
1143
1144 // Compute the number of locals and expression stack elements.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001145 int stack_locals_count = scope_info->StackLocalCount();
1146 int heap_locals_count = scope_info->ContextLocalCount();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001147 int expressions_count = ComputeExpressionsCount();
1148
1149 // Print stack-allocated local variables.
1150 if (stack_locals_count > 0) {
1151 accumulator->Add(" // stack-allocated locals\n");
1152 }
1153 for (int i = 0; i < stack_locals_count; i++) {
1154 accumulator->Add(" var ");
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001155 accumulator->PrintName(scope_info->StackLocalName(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001156 accumulator->Add(" = ");
1157 if (i < expressions_count) {
1158 accumulator->Add("%o", GetExpression(i));
1159 } else {
1160 accumulator->Add("// no expression found - inconsistent frame?");
1161 }
1162 accumulator->Add("\n");
1163 }
1164
1165 // Try to get hold of the context of this frame.
1166 Context* context = NULL;
1167 if (this->context() != NULL && this->context()->IsContext()) {
1168 context = Context::cast(this->context());
1169 }
1170
1171 // Print heap-allocated local variables.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001172 if (heap_locals_count > 0) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001173 accumulator->Add(" // heap-allocated locals\n");
1174 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001175 for (int i = 0; i < heap_locals_count; i++) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001176 accumulator->Add(" var ");
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001177 accumulator->PrintName(scope_info->ContextLocalName(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001178 accumulator->Add(" = ");
1179 if (context != NULL) {
1180 if (i < context->length()) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001181 accumulator->Add("%o", context->get(Context::MIN_CONTEXT_SLOTS + i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001182 } else {
1183 accumulator->Add(
1184 "// warning: missing context slot - inconsistent frame?");
1185 }
1186 } else {
1187 accumulator->Add("// warning: no context found - inconsistent frame?");
1188 }
1189 accumulator->Add("\n");
1190 }
1191
1192 // Print the expression stack.
kasper.lund7276f142008-07-30 08:49:36 +00001193 int expressions_start = stack_locals_count;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001194 if (expressions_start < expressions_count) {
1195 accumulator->Add(" // expression stack (top to bottom)\n");
1196 }
1197 for (int i = expressions_count - 1; i >= expressions_start; i--) {
1198 if (IsExpressionInsideHandler(i)) continue;
1199 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1200 }
1201
1202 // Print details about the function.
1203 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1204 SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
1205 accumulator->Add("--------- s o u r c e c o d e ---------\n");
1206 shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
1207 accumulator->Add("\n-----------------------------------------\n");
1208 }
1209
1210 accumulator->Add("}\n\n");
1211}
1212
1213
1214void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1215 PrintMode mode,
1216 int index) const {
1217 int actual = ComputeParametersCount();
1218 int expected = -1;
1219 Object* function = this->function();
1220 if (function->IsJSFunction()) {
1221 expected = JSFunction::cast(function)->shared()->formal_parameter_count();
1222 }
1223
1224 PrintIndex(accumulator, mode, index);
1225 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1226 if (mode == OVERVIEW) {
1227 accumulator->Add("\n");
1228 return;
1229 }
1230 accumulator->Add(" {\n");
1231
1232 // Print actual arguments.
1233 if (actual > 0) accumulator->Add(" // actual arguments\n");
1234 for (int i = 0; i < actual; i++) {
1235 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1236 if (expected != -1 && i >= expected) {
1237 accumulator->Add(" // not passed to callee");
1238 }
1239 accumulator->Add("\n");
1240 }
1241
1242 accumulator->Add("}\n\n");
1243}
1244
1245
1246void EntryFrame::Iterate(ObjectVisitor* v) const {
1247 StackHandlerIterator it(this, top_handler());
1248 ASSERT(!it.done());
1249 StackHandler* handler = it.handler();
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001250 ASSERT(handler->is_js_entry());
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001251 handler->Iterate(v, LookupCode());
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001252#ifdef DEBUG
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001253 // Make sure that the entry frame does not contain more than one
1254 // stack handler.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001255 it.Advance();
1256 ASSERT(it.done());
1257#endif
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001258 IteratePc(v, pc_address(), LookupCode());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001259}
1260
1261
1262void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
1263 const int offset = StandardFrameConstants::kContextOffset;
1264 Object** base = &Memory::Object_at(sp());
1265 Object** limit = &Memory::Object_at(fp() + offset) + 1;
1266 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1267 StackHandler* handler = it.handler();
1268 // Traverse pointers down to - but not including - the next
1269 // handler in the handler chain. Update the base to skip the
1270 // handler and allow the handler to traverse its own pointers.
1271 const Address address = handler->address();
1272 v->VisitPointers(base, reinterpret_cast<Object**>(address));
1273 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1274 // Traverse the pointers in the handler itself.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001275 handler->Iterate(v, LookupCode());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001276 }
1277 v->VisitPointers(base, limit);
1278}
1279
1280
1281void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1282 IterateExpressions(v);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001283 IteratePc(v, pc_address(), LookupCode());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001284}
1285
1286
1287void InternalFrame::Iterate(ObjectVisitor* v) const {
1288 // Internal frames only have object pointers on the expression stack
1289 // as they never have any arguments.
1290 IterateExpressions(v);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001291 IteratePc(v, pc_address(), LookupCode());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001292}
1293
1294
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001295void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001296 Object** base = &Memory::Object_at(sp());
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00001297 Object** limit = &Memory::Object_at(fp() +
1298 kFirstRegisterParameterFrameOffset);
1299 v->VisitPointers(base, limit);
1300 base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset);
1301 const int offset = StandardFrameConstants::kContextOffset;
1302 limit = &Memory::Object_at(fp() + offset) + 1;
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001303 v->VisitPointers(base, limit);
1304 IteratePc(v, pc_address(), LookupCode());
1305}
1306
1307
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00001308Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
1309 return fp() + StandardFrameConstants::kCallerSPOffset;
1310}
1311
1312
1313Code* StubFailureTrampolineFrame::unchecked_code() const {
1314 int i = 0;
1315 for (; i <= StubFailureTrampolineStub::kMaxExtraExpressionStackCount; ++i) {
1316 Code* trampoline;
1317 StubFailureTrampolineStub(i).FindCodeInCache(&trampoline, isolate());
1318 ASSERT(trampoline != NULL);
1319 Address current_pc = pc();
1320 Address code_start = trampoline->instruction_start();
1321 Address code_end = code_start + trampoline->instruction_size();
1322 if (code_start <= current_pc && current_pc < code_end) {
1323 return trampoline;
1324 }
1325 }
1326 UNREACHABLE();
1327 return NULL;
1328}
1329
1330
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001331// -------------------------------------------------------------------------
1332
1333
1334JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
1335 ASSERT(n >= 0);
1336 for (int i = 0; i <= n; i++) {
1337 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1338 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1339 iterator_.Advance();
1340 }
1341 UNREACHABLE();
1342 return NULL;
1343}
1344
1345
1346// -------------------------------------------------------------------------
1347
1348
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001349static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1350 MapWord map_word = object->map_word();
1351 return map_word.IsForwardingAddress() ?
1352 map_word.ToForwardingAddress()->map() : map_word.ToMap();
1353}
1354
1355
1356static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1357 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1358}
1359
1360
1361#ifdef DEBUG
1362static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1363 Map* map = GcSafeMapOfCodeSpaceObject(code);
1364 ASSERT(map == code->GetHeap()->code_map());
1365 Address start = code->address();
1366 Address end = code->address() + code->SizeFromMap(map);
1367 return start <= addr && addr < end;
1368}
1369#endif
1370
1371
1372Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1373 Address inner_pointer) {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001374 Code* code = reinterpret_cast<Code*>(object);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001375 ASSERT(code != NULL && GcSafeCodeContains(code, inner_pointer));
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001376 return code;
1377}
1378
1379
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001380Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1381 Address inner_pointer) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001382 Heap* heap = isolate_->heap();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001383 // Check if the inner pointer points into a large object chunk.
jkummerow@chromium.org531dfe82012-03-20 13:01:16 +00001384 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001385 if (large_page != NULL) {
1386 return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1387 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001388
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001389 // Iterate through the page until we reach the end or find an object starting
1390 // after the inner pointer.
1391 Page* page = Page::FromAddress(inner_pointer);
1392
1393 Address addr = page->skip_list()->StartFor(inner_pointer);
1394
1395 Address top = heap->code_space()->top();
1396 Address limit = heap->code_space()->limit();
1397
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001398 while (true) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001399 if (addr == top && addr != limit) {
1400 addr = limit;
1401 continue;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001402 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001403
1404 HeapObject* obj = HeapObject::FromAddress(addr);
1405 int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1406 Address next_addr = addr + obj_size;
1407 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1408 addr = next_addr;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001409 }
1410}
1411
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001412
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001413InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1414 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001415 isolate_->counters()->pc_to_code()->Increment();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001416 ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize));
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001417 uint32_t hash = ComputeIntegerHash(
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001418 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)),
1419 v8::internal::kZeroHashSeed);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001420 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1421 InnerPointerToCodeCacheEntry* entry = cache(index);
1422 if (entry->inner_pointer == inner_pointer) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001423 isolate_->counters()->pc_to_code_cached()->Increment();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001424 ASSERT(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001425 } else {
1426 // Because this code may be interrupted by a profiling signal that
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001427 // also queries the cache, we cannot update inner_pointer before the code
1428 // has been set. Otherwise, we risk trying to use a cache entry before
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001429 // the code has been computed.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001430 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001431 entry->safepoint_entry.Reset();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001432 entry->inner_pointer = inner_pointer;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001433 }
1434 return entry;
1435}
1436
1437
1438// -------------------------------------------------------------------------
1439
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001440int NumRegs(RegList reglist) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +00001441 return CompilerIntrinsics::CountSetBits(reglist);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001442}
1443
1444
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001445struct JSCallerSavedCodeData {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001446 int reg_code[kNumJSCallerSaved];
1447};
1448
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001449JSCallerSavedCodeData caller_saved_code_data;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001450
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001451void SetUpJSCallerSavedCodeData() {
1452 int i = 0;
1453 for (int r = 0; r < kNumRegs; r++)
1454 if ((kJSCallerSaved & (1 << r)) != 0)
1455 caller_saved_code_data.reg_code[i++] = r;
1456
1457 ASSERT(i == kNumJSCallerSaved);
1458}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001459
1460int JSCallerSavedCode(int n) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001461 ASSERT(0 <= n && n < kNumJSCallerSaved);
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001462 return caller_saved_code_data.reg_code[n];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001463}
1464
1465
ager@chromium.org357bf652010-04-12 11:30:10 +00001466#define DEFINE_WRAPPER(type, field) \
1467class field##_Wrapper : public ZoneObject { \
1468 public: /* NOLINT */ \
1469 field##_Wrapper(const field& original) : frame_(original) { \
1470 } \
1471 field frame_; \
1472};
1473STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1474#undef DEFINE_WRAPPER
1475
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001476static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
ager@chromium.org357bf652010-04-12 11:30:10 +00001477#define FRAME_TYPE_CASE(type, field) \
1478 case StackFrame::type: { \
1479 field##_Wrapper* wrapper = \
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001480 new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
ager@chromium.org357bf652010-04-12 11:30:10 +00001481 return &wrapper->frame_; \
1482 }
1483
1484 switch (frame->type()) {
1485 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1486 default: UNREACHABLE();
1487 }
1488#undef FRAME_TYPE_CASE
1489 return NULL;
1490}
1491
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001492Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001493 ZoneList<StackFrame*> list(10, zone);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001494 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001495 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1496 list.Add(frame, zone);
ager@chromium.org357bf652010-04-12 11:30:10 +00001497 }
1498 return list.ToVector();
1499}
1500
1501
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001502} } // namespace v8::internal