blob: a8fe6bb7b61b2524c6f84313370ab665b234424e [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/frames.h"
6
7#include <sstream>
8
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/ast/ast.h"
10#include "src/ast/scopeinfo.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/base/bits.h"
12#include "src/deoptimizer.h"
13#include "src/frames-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/full-codegen/full-codegen.h"
15#include "src/register-configuration.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016#include "src/safepoint-table.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017#include "src/string-stream.h"
18#include "src/vm-state-inl.h"
Ben Murdochc5610432016-08-08 18:44:38 +010019#include "src/wasm/wasm-module.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020
Steve Blocka7e24c12009-10-30 11:49:00 +000021namespace v8 {
22namespace internal {
23
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024ReturnAddressLocationResolver
25 StackFrame::return_address_location_resolver_ = NULL;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010026
27
Steve Blocka7e24c12009-10-30 11:49:00 +000028// Iterator that supports traversing the stack handlers of a
29// particular frame. Needs to know the top of the handler chain.
30class StackHandlerIterator BASE_EMBEDDED {
31 public:
32 StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
33 : limit_(frame->fp()), handler_(handler) {
34 // Make sure the handler has already been unwound to this frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035 DCHECK(frame->sp() <= handler->address());
Steve Blocka7e24c12009-10-30 11:49:00 +000036 }
37
38 StackHandler* handler() const { return handler_; }
39
40 bool done() {
41 return handler_ == NULL || handler_->address() > limit_;
42 }
43 void Advance() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +000045 handler_ = handler_->next();
46 }
47
48 private:
49 const Address limit_;
50 StackHandler* handler_;
51};
52
53
54// -------------------------------------------------------------------------
55
56
57#define INITIALIZE_SINGLETON(type, field) field##_(this),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
59 bool can_access_heap_objects)
Ben Murdoch8b112d22011-06-08 16:22:53 +010060 : isolate_(isolate),
61 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
62 frame_(NULL), handler_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063 can_access_heap_objects_(can_access_heap_objects) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010064}
Steve Blocka7e24c12009-10-30 11:49:00 +000065#undef INITIALIZE_SINGLETON
66
67
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068StackFrameIterator::StackFrameIterator(Isolate* isolate)
69 : StackFrameIteratorBase(isolate, true) {
70 Reset(isolate->thread_local_top());
71}
72
73
74StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
75 : StackFrameIteratorBase(isolate, true) {
76 Reset(t);
77}
78
79
80void StackFrameIterator::Advance() {
81 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +000082 // Compute the state of the calling frame before restoring
83 // callee-saved registers and unwinding handlers. This allows the
84 // frame code that computes the caller state to access the top
85 // handler and the value of any callee-saved register if needed.
86 StackFrame::State state;
87 StackFrame::Type type = frame_->GetCallerState(&state);
88
89 // Unwind handlers corresponding to the current frame.
90 StackHandlerIterator it(frame_, handler_);
91 while (!it.done()) it.Advance();
92 handler_ = it.handler();
93
94 // Advance to the calling frame.
95 frame_ = SingletonFor(type, &state);
96
97 // When we're done iterating over the stack frames, the handler
98 // chain must have been completely unwound.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099 DCHECK(!done() || handler_ == NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000100}
101
102
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103void StackFrameIterator::Reset(ThreadLocalTop* top) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000104 StackFrame::State state;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 StackFrame::Type type = ExitFrame::GetStateForFramePointer(
106 Isolate::c_entry_fp(top), &state);
107 handler_ = StackHandler::FromAddress(Isolate::handler(top));
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 frame_ = SingletonFor(type, &state);
109}
110
111
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
Steve Blocka7e24c12009-10-30 11:49:00 +0000113 StackFrame::State* state) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000114 StackFrame* result = SingletonFor(type);
Ben Murdochc5610432016-08-08 18:44:38 +0100115 DCHECK((!result) == (type == StackFrame::NONE));
116 if (result) result->state_ = *state;
Steve Blocka7e24c12009-10-30 11:49:00 +0000117 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) \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100123 case StackFrame::type: \
124 return &field##_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000125
Steve Blocka7e24c12009-10-30 11:49:00 +0000126 switch (type) {
127 case StackFrame::NONE: return NULL;
128 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
129 default: break;
130 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100131 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000132
133#undef FRAME_TYPE_CASE
134}
135
Steve Blocka7e24c12009-10-30 11:49:00 +0000136// -------------------------------------------------------------------------
137
Ben Murdochda12d292016-06-02 14:46:10 +0100138JavaScriptFrameIterator::JavaScriptFrameIterator(Isolate* isolate,
139 StackFrame::Id id)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140 : iterator_(isolate) {
141 while (!done()) {
142 Advance();
143 if (frame()->id() == id) return;
144 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000145}
146
147
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148void JavaScriptFrameIterator::Advance() {
149 do {
150 iterator_.Advance();
151 } while (!iterator_.done() && !iterator_.frame()->is_java_script());
152}
153
154
155void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
156 if (!frame()->has_adapted_arguments()) return;
157 iterator_.Advance();
158 DCHECK(iterator_.frame()->is_arguments_adaptor());
159}
160
161
162// -------------------------------------------------------------------------
163
Ben Murdoch8b112d22011-06-08 16:22:53 +0100164StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
Ben Murdochc5610432016-08-08 18:44:38 +0100165 : iterator_(isolate) {
166 if (!done() && !IsValidFrame(iterator_.frame())) Advance();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100167}
168
169
Steve Blocka7e24c12009-10-30 11:49:00 +0000170void StackTraceFrameIterator::Advance() {
Ben Murdochc5610432016-08-08 18:44:38 +0100171 do {
172 iterator_.Advance();
173 } while (!done() && !IsValidFrame(iterator_.frame()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000174}
175
Ben Murdochc5610432016-08-08 18:44:38 +0100176bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
177 if (frame->is_java_script()) {
178 JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame);
179 if (!jsFrame->function()->IsJSFunction()) return false;
180 Object* script = jsFrame->function()->shared()->script();
Leon Clarke4515c472010-02-03 11:58:03 +0000181 // Don't show functions from native scripts to user.
182 return (script->IsScript() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 Script::TYPE_NATIVE != Script::cast(script)->type());
Ben Murdochc5610432016-08-08 18:44:38 +0100184 }
185 // apart from javascript, only wasm is valid
186 return frame->is_wasm();
Leon Clarke4515c472010-02-03 11:58:03 +0000187}
188
Steve Blocka7e24c12009-10-30 11:49:00 +0000189
190// -------------------------------------------------------------------------
191
192
193SafeStackFrameIterator::SafeStackFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100194 Isolate* isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195 Address fp, Address sp, Address js_entry_sp)
196 : StackFrameIteratorBase(isolate, false),
197 low_bound_(sp),
198 high_bound_(js_entry_sp),
199 top_frame_type_(StackFrame::NONE),
200 external_callback_scope_(isolate->external_callback_scope()) {
201 StackFrame::State state;
202 StackFrame::Type type;
Steve Block44f0eee2011-05-26 01:26:41 +0100203 ThreadLocalTop* top = isolate->thread_local_top();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 if (IsValidTop(top)) {
205 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
206 top_frame_type_ = type;
207 } else if (IsValidStackAddress(fp)) {
208 DCHECK(fp != NULL);
209 state.fp = fp;
210 state.sp = sp;
211 state.pc_address = StackFrame::ResolveReturnAddressLocation(
212 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
213 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
214 // we check only that kMarkerOffset is within the stack bounds and do
215 // compile time check that kContextOffset slot is pushed on the stack before
216 // kMarkerOffset.
Ben Murdochda12d292016-06-02 14:46:10 +0100217 STATIC_ASSERT(StandardFrameConstants::kFunctionOffset <
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 StandardFrameConstants::kContextOffset);
Ben Murdochda12d292016-06-02 14:46:10 +0100219 Address frame_marker = fp + StandardFrameConstants::kFunctionOffset;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220 if (IsValidStackAddress(frame_marker)) {
221 type = StackFrame::ComputeType(this, &state);
222 top_frame_type_ = type;
223 } else {
224 // Mark the frame as JAVA_SCRIPT if we cannot determine its type.
225 // The frame anyways will be skipped.
226 type = StackFrame::JAVA_SCRIPT;
227 // Top frame is incomplete so we cannot reliably determine its type.
228 top_frame_type_ = StackFrame::NONE;
229 }
230 } else {
231 return;
232 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 frame_ = SingletonFor(type, &state);
Ben Murdochc5610432016-08-08 18:44:38 +0100234 if (frame_) Advance();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100235}
236
237
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
239 Address c_entry_fp = Isolate::c_entry_fp(top);
240 if (!IsValidExitFrame(c_entry_fp)) return false;
241 // There should be at least one JS_ENTRY stack handler.
242 Address handler = Isolate::handler(top);
243 if (handler == NULL) return false;
244 // Check that there are no js frames on top of the native frames.
245 return c_entry_fp < handler;
246}
247
248
249void SafeStackFrameIterator::AdvanceOneFrame() {
250 DCHECK(!done());
251 StackFrame* last_frame = frame_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000252 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000253 // Before advancing to the next stack frame, perform pointer validity tests.
254 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
255 frame_ = NULL;
256 return;
257 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000258
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259 // Advance to the previous frame.
260 StackFrame::State state;
261 StackFrame::Type type = frame_->GetCallerState(&state);
262 frame_ = SingletonFor(type, &state);
Ben Murdochc5610432016-08-08 18:44:38 +0100263 if (!frame_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000264
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265 // Check that we have actually moved to the previous frame in the stack.
266 if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
267 frame_ = NULL;
268 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000269}
270
271
272bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
273 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
274}
275
276
277bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
278 StackFrame::State state;
279 if (frame->is_entry() || frame->is_entry_construct()) {
280 // See EntryFrame::GetCallerState. It computes the caller FP address
281 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
282 // sure that caller FP address is valid.
283 Address caller_fp = Memory::Address_at(
284 frame->fp() + EntryFrameConstants::kCallerFPOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 if (!IsValidExitFrame(caller_fp)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000286 } else if (frame->is_arguments_adaptor()) {
287 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
288 // the number of arguments is stored on stack as Smi. We need to check
289 // that it really an Smi.
290 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
291 GetExpression(0);
292 if (!number_of_args->IsSmi()) {
293 return false;
294 }
295 }
296 frame->ComputeCallerState(&state);
297 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 SingletonFor(frame->GetCallerState(&state)) != NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000299}
300
301
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
303 if (!IsValidStackAddress(fp)) return false;
304 Address sp = ExitFrame::ComputeStackPointer(fp);
305 if (!IsValidStackAddress(sp)) return false;
306 StackFrame::State state;
307 ExitFrame::FillState(fp, sp, &state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308 return *state.pc_address != NULL;
309}
310
311
312void SafeStackFrameIterator::Advance() {
313 while (true) {
314 AdvanceOneFrame();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100315 if (done()) break;
316 ExternalCallbackScope* last_callback_scope = NULL;
317 while (external_callback_scope_ != NULL &&
318 external_callback_scope_->scope_address() < frame_->fp()) {
319 // As long as the setup of a frame is not atomic, we may happen to be
320 // in an interval where an ExternalCallbackScope is already created,
321 // but the frame is not yet entered. So we are actually observing
322 // the previous frame.
323 // Skip all the ExternalCallbackScope's that are below the current fp.
324 last_callback_scope = external_callback_scope_;
325 external_callback_scope_ = external_callback_scope_->previous();
326 }
327 if (frame_->is_java_script()) break;
328 if (frame_->is_exit()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329 // Some of the EXIT frames may have ExternalCallbackScope allocated on
330 // top of them. In that case the scope corresponds to the first EXIT
331 // frame beneath it. There may be other EXIT frames on top of the
332 // ExternalCallbackScope, just skip them as we cannot collect any useful
333 // information about them.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100334 if (last_callback_scope) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335 frame_->state_.pc_address =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100336 last_callback_scope->callback_entrypoint_address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100338 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000340 }
341}
342
343
344// -------------------------------------------------------------------------
345
346
Ben Murdoch8b112d22011-06-08 16:22:53 +0100347Code* StackFrame::GetSafepointData(Isolate* isolate,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100348 Address inner_pointer,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100349 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100350 unsigned* stack_slots) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100351 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
352 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100353 if (!entry->safepoint_entry.is_valid()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100354 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355 DCHECK(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100356 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000357 DCHECK(entry->safepoint_entry.Equals(
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100358 entry->code->GetSafepointEntry(inner_pointer)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100359 }
360
361 // Fill in the results and return the code.
362 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100363 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100364 *stack_slots = code->stack_slots();
365 return code;
366}
367
368
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100369#ifdef DEBUG
370static bool GcSafeCodeContains(HeapObject* object, Address addr);
371#endif
372
373
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374void StackFrame::IteratePc(ObjectVisitor* v, Address* pc_address,
375 Address* constant_pool_address, Code* holder) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100376 Address pc = *pc_address;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 DCHECK(GcSafeCodeContains(holder, pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100378 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
379 Object* code = holder;
380 v->VisitPointer(&code);
381 if (code != holder) {
382 holder = reinterpret_cast<Code*>(code);
383 pc = holder->instruction_start() + pc_offset;
384 *pc_address = pc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385 if (FLAG_enable_embedded_constant_pool && constant_pool_address) {
386 *constant_pool_address = holder->constant_pool();
387 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000388 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000389}
390
391
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100392void StackFrame::SetReturnAddressLocationResolver(
393 ReturnAddressLocationResolver resolver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394 DCHECK(return_address_location_resolver_ == NULL);
395 return_address_location_resolver_ = resolver;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100396}
397
Ben Murdochda12d292016-06-02 14:46:10 +0100398static bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
399 Code* interpreter_entry_trampoline =
400 isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
401 Code* interpreter_bytecode_dispatch =
402 isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
403
404 return (pc >= interpreter_entry_trampoline->instruction_start() &&
405 pc < interpreter_entry_trampoline->instruction_end()) ||
406 (pc >= interpreter_bytecode_dispatch->instruction_start() &&
407 pc < interpreter_bytecode_dispatch->instruction_end());
408}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100409
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000410StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
411 State* state) {
412 DCHECK(state->fp != NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000413
Ben Murdochda12d292016-06-02 14:46:10 +0100414#if defined(USE_SIMULATOR)
415 MSAN_MEMORY_IS_INITIALIZED(
416 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset,
417 kPointerSize);
418#endif
419 Object* marker = Memory::Object_at(
420 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421 if (!iterator->can_access_heap_objects_) {
422 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really
423 // means that we are being called from the profiler, which can interrupt
424 // the VM with a signal at any arbitrary instruction, with essentially
425 // anything on the stack. So basically none of these checks are 100%
426 // reliable.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100427#if defined(USE_SIMULATOR)
428 MSAN_MEMORY_IS_INITIALIZED(
Ben Murdochda12d292016-06-02 14:46:10 +0100429 state->fp + StandardFrameConstants::kFunctionOffset, kPointerSize);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100430#endif
Ben Murdochda12d292016-06-02 14:46:10 +0100431 Object* maybe_function =
432 Memory::Object_at(state->fp + StandardFrameConstants::kFunctionOffset);
433 if (!marker->IsSmi()) {
434 if (maybe_function->IsSmi()) {
435 return NONE;
436 } else if (FLAG_ignition && IsInterpreterFramePc(iterator->isolate(),
437 *(state->pc_address))) {
438 return INTERPRETED;
439 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000440 return JAVA_SCRIPT;
Ben Murdochda12d292016-06-02 14:46:10 +0100441 }
442 }
443 } else {
444 // Look up the code object to figure out the type of the stack frame.
445 Code* code_obj =
446 GetContainingCode(iterator->isolate(), *(state->pc_address));
447 if (code_obj != nullptr) {
448 if (code_obj->is_interpreter_entry_trampoline() ||
449 code_obj->is_interpreter_enter_bytecode_dispatch()) {
450 return INTERPRETED;
451 }
452 switch (code_obj->kind()) {
453 case Code::BUILTIN:
454 if (marker->IsSmi()) break;
455 // We treat frames for BUILTIN Code objects as OptimizedFrame for now
456 // (all the builtins with JavaScript linkage are actually generated
457 // with TurboFan currently, so this is sound).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458 return OPTIMIZED;
Ben Murdochda12d292016-06-02 14:46:10 +0100459 case Code::FUNCTION:
460 return JAVA_SCRIPT;
461 case Code::OPTIMIZED_FUNCTION:
462 return OPTIMIZED;
463 case Code::WASM_FUNCTION:
464 return WASM;
465 case Code::WASM_TO_JS_FUNCTION:
466 return WASM_TO_JS;
467 case Code::JS_TO_WASM_FUNCTION:
468 return JS_TO_WASM;
469 default:
470 // All other types should have an explicit marker
471 break;
472 }
473 } else {
474 return NONE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100476 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477
Ben Murdochda12d292016-06-02 14:46:10 +0100478 DCHECK(marker->IsSmi());
479 StackFrame::Type candidate =
480 static_cast<StackFrame::Type>(Smi::cast(marker)->value());
481 switch (candidate) {
482 case ENTRY:
483 case ENTRY_CONSTRUCT:
484 case EXIT:
485 case STUB:
486 case STUB_FAILURE_TRAMPOLINE:
487 case INTERNAL:
488 case CONSTRUCT:
489 case ARGUMENTS_ADAPTOR:
Ben Murdochda12d292016-06-02 14:46:10 +0100490 case WASM_TO_JS:
491 case WASM:
Ben Murdochc5610432016-08-08 18:44:38 +0100492 return candidate;
493 case JS_TO_WASM:
Ben Murdochda12d292016-06-02 14:46:10 +0100494 case JAVA_SCRIPT:
495 case OPTIMIZED:
496 case INTERPRETED:
497 default:
498 // Unoptimized and optimized JavaScript frames, including
499 // interpreted frames, should never have a StackFrame::Type
500 // marker. If we find one, we're likely being called from the
501 // profiler in a bogus stack frame.
502 return NONE;
503 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000504}
505
506
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507#ifdef DEBUG
508bool StackFrame::can_access_heap_objects() const {
509 return iterator_->can_access_heap_objects_;
510}
511#endif
512
Steve Blocka7e24c12009-10-30 11:49:00 +0000513
514StackFrame::Type StackFrame::GetCallerState(State* state) const {
515 ComputeCallerState(state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000516 return ComputeType(iterator_, state);
517}
518
519
520Address StackFrame::UnpaddedFP() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000521 return fp();
Steve Blocka7e24c12009-10-30 11:49:00 +0000522}
523
524
Iain Merrick75681382010-08-19 15:07:18 +0100525Code* EntryFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000526 return isolate()->heap()->js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000527}
528
529
530void EntryFrame::ComputeCallerState(State* state) const {
531 GetCallerState(state);
532}
533
534
Steve Block6ded16b2010-05-10 14:33:55 +0100535void EntryFrame::SetCallerFp(Address caller_fp) {
536 const int offset = EntryFrameConstants::kCallerFPOffset;
537 Memory::Address_at(this->fp() + offset) = caller_fp;
538}
539
540
Steve Blocka7e24c12009-10-30 11:49:00 +0000541StackFrame::Type EntryFrame::GetCallerState(State* state) const {
542 const int offset = EntryFrameConstants::kCallerFPOffset;
543 Address fp = Memory::Address_at(this->fp() + offset);
544 return ExitFrame::GetStateForFramePointer(fp, state);
545}
546
547
Iain Merrick75681382010-08-19 15:07:18 +0100548Code* EntryConstructFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000549 return isolate()->heap()->js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000550}
551
552
Steve Blockd0582a62009-12-15 09:54:21 +0000553Object*& ExitFrame::code_slot() const {
554 const int offset = ExitFrameConstants::kCodeOffset;
555 return Memory::Object_at(fp() + offset);
556}
557
558
Iain Merrick75681382010-08-19 15:07:18 +0100559Code* ExitFrame::unchecked_code() const {
560 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000561}
562
563
564void ExitFrame::ComputeCallerState(State* state) const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100565 // Set up the caller state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000566 state->sp = caller_sp();
567 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100568 state->pc_address = ResolveReturnAddressLocation(
569 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000571 state->constant_pool_address = reinterpret_cast<Address*>(
572 fp() + ExitFrameConstants::kConstantPoolOffset);
573 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000574}
575
576
Steve Block6ded16b2010-05-10 14:33:55 +0100577void ExitFrame::SetCallerFp(Address caller_fp) {
578 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
579}
580
581
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100582void ExitFrame::Iterate(ObjectVisitor* v) const {
583 // The arguments are traversed as part of the expression stack of
584 // the calling frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100586 v->VisitPointer(&code_slot());
587}
588
589
Steve Blocka7e24c12009-10-30 11:49:00 +0000590Address ExitFrame::GetCallerStackPointer() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100591 return fp() + ExitFrameConstants::kCallerSPOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +0000592}
593
594
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100595StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
596 if (fp == 0) return NONE;
597 Address sp = ComputeStackPointer(fp);
598 FillState(fp, sp, state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000599 DCHECK(*state->pc_address != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100600 return EXIT;
601}
602
603
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000604Address ExitFrame::ComputeStackPointer(Address fp) {
605 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
606}
607
608
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100609void ExitFrame::FillState(Address fp, Address sp, State* state) {
610 state->sp = sp;
611 state->fp = fp;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100612 state->pc_address = ResolveReturnAddressLocation(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000613 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000614 // The constant pool recorded in the exit frame is not associated
615 // with the pc in this state (the return address into a C entry
616 // stub). ComputeCallerState will retrieve the constant pool
617 // together with the associated caller pc.
618 state->constant_pool_address = NULL;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100619}
620
Steve Blocka7e24c12009-10-30 11:49:00 +0000621Address StandardFrame::GetExpressionAddress(int n) const {
622 const int offset = StandardFrameConstants::kExpressionsOffset;
623 return fp() + offset - n * kPointerSize;
624}
625
Ben Murdoch097c5b22016-05-18 11:27:45 +0100626Address InterpretedFrame::GetExpressionAddress(int n) const {
627 const int offset = InterpreterFrameConstants::kExpressionsOffset;
628 return fp() + offset - n * kPointerSize;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000629}
630
Steve Blocka7e24c12009-10-30 11:49:00 +0000631int StandardFrame::ComputeExpressionsCount() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100632 Address base = GetExpressionAddress(0);
633 Address limit = sp() - kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 DCHECK(base >= limit); // stack grows downwards
Steve Blocka7e24c12009-10-30 11:49:00 +0000635 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000636 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000637}
638
639
640void StandardFrame::ComputeCallerState(State* state) const {
641 state->sp = caller_sp();
642 state->fp = caller_fp();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100643 state->pc_address = ResolveReturnAddressLocation(
644 reinterpret_cast<Address*>(ComputePCAddress(fp())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000645 state->constant_pool_address =
646 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000647}
648
649
Steve Block6ded16b2010-05-10 14:33:55 +0100650void StandardFrame::SetCallerFp(Address caller_fp) {
651 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
652 caller_fp;
653}
654
655
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000656void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100657 // Make sure that we're not doing "safe" stack frame iteration. We cannot
658 // possibly find pointers in optimized frames in that state.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000659 DCHECK(can_access_heap_objects());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100660
661 // Compute the safepoint information.
662 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100663 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100664 Code* code = StackFrame::GetSafepointData(
Ben Murdoch8b112d22011-06-08 16:22:53 +0100665 isolate(), pc(), &safepoint_entry, &stack_slots);
Ben Murdochda12d292016-06-02 14:46:10 +0100666 unsigned slot_space = stack_slots * kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100667
Ben Murdochda12d292016-06-02 14:46:10 +0100668 // Determine the fixed header and spill slot area size.
669 int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp;
670 Object* marker =
671 Memory::Object_at(fp() + CommonFrameConstants::kContextOrFrameTypeOffset);
672 if (marker->IsSmi()) {
673 StackFrame::Type candidate =
674 static_cast<StackFrame::Type>(Smi::cast(marker)->value());
675 switch (candidate) {
676 case ENTRY:
677 case ENTRY_CONSTRUCT:
678 case EXIT:
679 case STUB_FAILURE_TRAMPOLINE:
680 case ARGUMENTS_ADAPTOR:
681 case STUB:
682 case INTERNAL:
683 case CONSTRUCT:
684 case JS_TO_WASM:
685 case WASM_TO_JS:
686 case WASM:
687 frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
688 break;
689 case JAVA_SCRIPT:
690 case OPTIMIZED:
691 case INTERPRETED:
692 // These frame types have a context, but they are actually stored
693 // in the place on the stack that one finds the frame type.
694 UNREACHABLE();
695 break;
696 case NONE:
697 case NUMBER_OF_TYPES:
698 case MANUAL:
699 UNREACHABLE();
700 break;
701 }
702 }
703 slot_space -=
704 (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp);
705
706 Object** frame_header_base = &Memory::Object_at(fp() - frame_header_size);
Ben Murdochc5610432016-08-08 18:44:38 +0100707 Object** frame_header_limit =
708 &Memory::Object_at(fp() - StandardFrameConstants::kCPSlotSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100709 Object** parameters_base = &Memory::Object_at(sp());
Ben Murdochda12d292016-06-02 14:46:10 +0100710 Object** parameters_limit = frame_header_base - slot_space / kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100711
Ben Murdochb8e0da22011-05-16 14:20:40 +0100712 // Visit the parameters that may be on top of the saved registers.
713 if (safepoint_entry.argument_count() > 0) {
714 v->VisitPointers(parameters_base,
715 parameters_base + safepoint_entry.argument_count());
716 parameters_base += safepoint_entry.argument_count();
717 }
718
719 // Skip saved double registers.
720 if (safepoint_entry.has_doubles()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000721 // Number of doubles not known at snapshot time.
722 DCHECK(!isolate()->serializer_enabled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723 parameters_base +=
724 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
725 ->num_allocatable_double_registers() *
Ben Murdochb8e0da22011-05-16 14:20:40 +0100726 kDoubleSize / kPointerSize;
727 }
728
Ben Murdochb0fe1622011-05-05 13:52:32 +0100729 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100730 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100731 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100732 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100733 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
734 v->VisitPointer(parameters_base + reg_stack_index);
735 }
736 }
737 // Skip the words containing the register values.
738 parameters_base += kNumSafepointRegisters;
739 }
740
741 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100742 uint8_t* safepoint_bits = safepoint_entry.bits();
743 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100744
745 // Visit the rest of the parameters.
Ben Murdochda12d292016-06-02 14:46:10 +0100746 if (!is_js_to_wasm() && !is_wasm()) {
747 // Non-WASM frames have tagged values as parameters.
748 v->VisitPointers(parameters_base, parameters_limit);
749 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100750
751 // Visit pointer spill slots and locals.
752 for (unsigned index = 0; index < stack_slots; index++) {
753 int byte_index = index >> kBitsPerByteLog2;
754 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100755 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100756 v->VisitPointer(parameters_limit + index);
757 }
758 }
759
Ben Murdochb0fe1622011-05-05 13:52:32 +0100760 // Visit the return address in the callee and incoming arguments.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000761 IteratePc(v, pc_address(), constant_pool_address(), code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000762
Ben Murdochda12d292016-06-02 14:46:10 +0100763 if (!is_wasm() && !is_wasm_to_js()) {
764 // Visit the context in stub frame and JavaScript frame.
765 // Visit the function in JavaScript frame.
766 v->VisitPointers(frame_header_base, frame_header_limit);
767 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000768}
769
770
771void StubFrame::Iterate(ObjectVisitor* v) const {
772 IterateCompiledFrame(v);
773}
774
775
776Code* StubFrame::unchecked_code() const {
777 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
778}
779
780
781Address StubFrame::GetCallerStackPointer() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100782 return fp() + ExitFrameConstants::kCallerSPOffset;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000783}
784
785
786int StubFrame::GetNumberOfIncomingArguments() const {
787 return 0;
788}
789
790
791void OptimizedFrame::Iterate(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000792 IterateCompiledFrame(v);
793}
794
795
796void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
797 Memory::Object_at(GetParameterSlot(index)) = value;
Steve Blocka7e24c12009-10-30 11:49:00 +0000798}
799
800
801bool JavaScriptFrame::IsConstructor() const {
802 Address fp = caller_fp();
803 if (has_adapted_arguments()) {
804 // Skip the arguments adaptor frame and look at the real caller.
805 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
806 }
807 return IsConstructFrame(fp);
808}
809
810
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000811bool JavaScriptFrame::HasInlinedFrames() const {
812 List<JSFunction*> functions(1);
813 GetFunctions(&functions);
814 return functions.length() > 1;
815}
816
817
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000818int JavaScriptFrame::GetArgumentsLength() const {
819 // If there is an arguments adaptor frame get the arguments length from it.
820 if (has_adapted_arguments()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100821 return ArgumentsAdaptorFrame::GetLength(caller_fp());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000822 } else {
823 return GetNumberOfIncomingArguments();
824 }
825}
826
827
Iain Merrick75681382010-08-19 15:07:18 +0100828Code* JavaScriptFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000829 return function()->code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000830}
831
832
Ben Murdoch8b112d22011-06-08 16:22:53 +0100833int JavaScriptFrame::GetNumberOfIncomingArguments() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000834 DCHECK(can_access_heap_objects() &&
Ben Murdoch8b112d22011-06-08 16:22:53 +0100835 isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
836
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837 return function()->shared()->internal_formal_parameter_count();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100838}
839
840
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100841Address JavaScriptFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100842 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100843}
844
845
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000846void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000847 DCHECK(functions->length() == 0);
848 functions->Add(function());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100849}
850
Ben Murdochc5610432016-08-08 18:44:38 +0100851void JavaScriptFrame::Summarize(List<FrameSummary>* functions,
852 FrameSummary::Mode mode) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 DCHECK(functions->length() == 0);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100854 Code* code = LookupCode();
855 int offset = static_cast<int>(pc() - code->instruction_start());
856 AbstractCode* abstract_code = AbstractCode::cast(code);
857 FrameSummary summary(receiver(), function(), abstract_code, offset,
Ben Murdochc5610432016-08-08 18:44:38 +0100858 IsConstructor(), mode);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100859 functions->Add(summary);
860}
861
Ben Murdochc5610432016-08-08 18:44:38 +0100862JSFunction* JavaScriptFrame::function() const {
863 return JSFunction::cast(function_slot_object());
864}
865
866Object* JavaScriptFrame::receiver() const { return GetParameter(-1); }
867
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000868int JavaScriptFrame::LookupExceptionHandlerInTable(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100869 int* stack_depth, HandlerTable::CatchPrediction* prediction) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870 Code* code = LookupCode();
871 DCHECK(!code->is_optimized_code());
872 HandlerTable* table = HandlerTable::cast(code->handler_table());
873 int pc_offset = static_cast<int>(pc() - code->entry());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100874 return table->LookupRange(pc_offset, stack_depth, prediction);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000875}
876
877
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
879 Address pc, FILE* file,
880 bool print_line_number) {
881 PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
882 function->PrintName(file);
883 int code_offset = static_cast<int>(pc - code->instruction_start());
884 PrintF(file, "+%d", code_offset);
885 if (print_line_number) {
886 SharedFunctionInfo* shared = function->shared();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100887 int source_pos = code->SourcePosition(code_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888 Object* maybe_script = shared->script();
889 if (maybe_script->IsScript()) {
890 Script* script = Script::cast(maybe_script);
891 int line = script->GetLineNumber(source_pos) + 1;
892 Object* script_name_raw = script->name();
893 if (script_name_raw->IsString()) {
894 String* script_name = String::cast(script->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000895 base::SmartArrayPointer<char> c_script_name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000896 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
897 PrintF(file, " at %s:%d", c_script_name.get(), line);
898 } else {
899 PrintF(file, " at <unknown>:%d", line);
900 }
901 } else {
902 PrintF(file, " at <unknown>:<unknown>");
903 }
904 }
905}
906
907
908void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100909 bool print_line_number) {
910 // constructor calls
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000911 DisallowHeapAllocation no_allocation;
912 JavaScriptFrameIterator it(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100913 while (!it.done()) {
914 if (it.frame()->is_java_script()) {
915 JavaScriptFrame* frame = it.frame();
916 if (frame->IsConstructor()) PrintF(file, "new ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917 PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
918 frame->pc(), file, print_line_number);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100919 if (print_args) {
920 // function arguments
921 // (we are intentionally only printing the actually
922 // supplied parameters, not all parameters required)
923 PrintF(file, "(this=");
924 frame->receiver()->ShortPrint(file);
925 const int length = frame->ComputeParametersCount();
926 for (int i = 0; i < length; i++) {
927 PrintF(file, ", ");
928 frame->GetParameter(i)->ShortPrint(file);
929 }
930 PrintF(file, ")");
931 }
932 break;
933 }
934 it.Advance();
935 }
936}
937
938
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000939void JavaScriptFrame::SaveOperandStack(FixedArray* store) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000940 int operands_count = store->length();
941 DCHECK_LE(operands_count, ComputeOperandsCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000942 for (int i = 0; i < operands_count; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000943 store->set(i, GetOperand(i));
944 }
945}
946
Ben Murdochda12d292016-06-02 14:46:10 +0100947namespace {
948
949bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) {
950 return code->is_turbofanned() && function->shared()->asm_function() &&
951 !FLAG_turbo_asm_deoptimization;
952}
953
954} // namespace
955
Ben Murdoch097c5b22016-05-18 11:27:45 +0100956FrameSummary::FrameSummary(Object* receiver, JSFunction* function,
957 AbstractCode* abstract_code, int code_offset,
Ben Murdochc5610432016-08-08 18:44:38 +0100958 bool is_constructor, Mode mode)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 : receiver_(receiver, function->GetIsolate()),
960 function_(function),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100961 abstract_code_(abstract_code),
962 code_offset_(code_offset),
Ben Murdochda12d292016-06-02 14:46:10 +0100963 is_constructor_(is_constructor) {
964 DCHECK(abstract_code->IsBytecodeArray() ||
965 Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION ||
Ben Murdochc5610432016-08-08 18:44:38 +0100966 CannotDeoptFromAsmCode(Code::cast(abstract_code), function) ||
967 mode == kApproximateSummary);
968}
969
970FrameSummary FrameSummary::GetFirst(JavaScriptFrame* frame) {
971 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
972 frame->Summarize(&frames);
973 return frames.first();
Ben Murdochda12d292016-06-02 14:46:10 +0100974}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000975
Ben Murdochb0fe1622011-05-05 13:52:32 +0100976void FrameSummary::Print() {
977 PrintF("receiver: ");
978 receiver_->ShortPrint();
979 PrintF("\nfunction: ");
980 function_->shared()->DebugName()->ShortPrint();
981 PrintF("\ncode: ");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100982 abstract_code_->ShortPrint();
983 if (abstract_code_->IsCode()) {
984 Code* code = abstract_code_->GetCode();
985 if (code->kind() == Code::FUNCTION) PrintF(" UNOPT ");
Ben Murdochda12d292016-06-02 14:46:10 +0100986 if (code->kind() == Code::OPTIMIZED_FUNCTION) {
Ben Murdochc5610432016-08-08 18:44:38 +0100987 if (function()->shared()->asm_function()) {
988 DCHECK(CannotDeoptFromAsmCode(code, *function()));
989 PrintF(" ASM ");
990 } else {
991 PrintF(" OPT (approximate)");
992 }
Ben Murdochda12d292016-06-02 14:46:10 +0100993 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100994 } else {
995 PrintF(" BYTECODE ");
996 }
997 PrintF("\npc: %d\n", code_offset_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100998}
999
Ben Murdochc5610432016-08-08 18:44:38 +01001000void OptimizedFrame::Summarize(List<FrameSummary>* frames,
1001 FrameSummary::Mode mode) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002 DCHECK(frames->length() == 0);
1003 DCHECK(is_optimized());
1004
1005 // Delegate to JS frame in absence of turbofan deoptimization.
1006 // TODO(turbofan): Revisit once we support deoptimization across the board.
Ben Murdochda12d292016-06-02 14:46:10 +01001007 Code* code = LookupCode();
1008 if (code->kind() == Code::BUILTIN ||
1009 CannotDeoptFromAsmCode(code, function())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001010 return JavaScriptFrame::Summarize(frames);
1011 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001012
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +01001014 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001015 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
Ben Murdochc5610432016-08-08 18:44:38 +01001016 if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
1017 DCHECK(data == nullptr);
1018 if (mode == FrameSummary::kApproximateSummary) {
1019 return JavaScriptFrame::Summarize(frames, mode);
1020 }
1021 FATAL("Missing deoptimization information for OptimizedFrame::Summarize.");
1022 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001023 FixedArray* const literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001024
1025 TranslationIterator it(data->TranslationByteArray(),
1026 data->TranslationIndex(deopt_index)->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001027 Translation::Opcode frame_opcode =
1028 static_cast<Translation::Opcode>(it.Next());
1029 DCHECK_EQ(Translation::BEGIN, frame_opcode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001030 it.Next(); // Drop frame count.
1031 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001032
1033 // We create the summary in reverse order because the frames
1034 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001035 bool is_constructor = IsConstructor();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001036 while (jsframe_count != 0) {
1037 frame_opcode = static_cast<Translation::Opcode>(it.Next());
1038 if (frame_opcode == Translation::JS_FRAME ||
1039 frame_opcode == Translation::INTERPRETED_FRAME) {
1040 jsframe_count--;
Ben Murdochda12d292016-06-02 14:46:10 +01001041 BailoutId const bailout_id = BailoutId(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001042 SharedFunctionInfo* const shared_info =
1043 SharedFunctionInfo::cast(literal_array->get(it.Next()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001044 it.Next(); // Skip height.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001045
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001046 // The translation commands are ordered and the function is always
1047 // at the first position, and the receiver is next.
1048 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
1049
1050 // Get the correct function in the optimized frame.
1051 JSFunction* function;
1052 if (opcode == Translation::LITERAL) {
1053 function = JSFunction::cast(literal_array->get(it.Next()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001054 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001055 CHECK_EQ(opcode, Translation::STACK_SLOT);
1056 function = JSFunction::cast(StackSlotAt(it.Next()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001057 }
1058 DCHECK_EQ(shared_info, function->shared());
1059
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001060 // If we are at a call, the receiver is always in a stack slot.
1061 // Otherwise we are not guaranteed to get the receiver value.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001062 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001063
1064 // Get the correct receiver in the optimized frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001065 Object* receiver;
Ben Murdoch257744e2011-11-30 15:57:28 +00001066 if (opcode == Translation::LITERAL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001067 receiver = literal_array->get(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001068 } else if (opcode == Translation::STACK_SLOT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001069 receiver = StackSlotAt(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001070 } else {
1071 // The receiver is not in a stack slot nor in a literal. We give up.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 it.Skip(Translation::NumberOfOperandsFor(opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001073 // TODO(3029): Materializing a captured object (or duplicated
1074 // object) is hard, we return undefined for now. This breaks the
1075 // produced stack trace, as constructor frames aren't marked as
1076 // such anymore.
1077 receiver = isolate()->heap()->undefined_value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001078 }
1079
Ben Murdoch097c5b22016-05-18 11:27:45 +01001080 AbstractCode* abstract_code;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001081
Ben Murdoch097c5b22016-05-18 11:27:45 +01001082 unsigned code_offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001083 if (frame_opcode == Translation::JS_FRAME) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001084 Code* code = shared_info->code();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001085 DeoptimizationOutputData* const output_data =
1086 DeoptimizationOutputData::cast(code->deoptimization_data());
1087 unsigned const entry =
Ben Murdochda12d292016-06-02 14:46:10 +01001088 Deoptimizer::GetOutputInfo(output_data, bailout_id, shared_info);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001089 code_offset = FullCodeGenerator::PcField::decode(entry);
1090 abstract_code = AbstractCode::cast(code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001091 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001092 DCHECK_EQ(frame_opcode, Translation::INTERPRETED_FRAME);
Ben Murdochda12d292016-06-02 14:46:10 +01001093 // BailoutId points to the next bytecode in the bytecode aray. Subtract
1094 // 1 to get the end of current bytecode.
1095 code_offset = bailout_id.ToInt() - 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001096 abstract_code = AbstractCode::cast(shared_info->bytecode_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001097 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001098 FrameSummary summary(receiver, function, abstract_code, code_offset,
1099 is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001100 frames->Add(summary);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001101 is_constructor = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001102 } else if (frame_opcode == Translation::CONSTRUCT_STUB_FRAME) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001103 // The next encountered JS_FRAME will be marked as a constructor call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001104 it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001105 DCHECK(!is_constructor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001106 is_constructor = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001107 } else {
1108 // Skip over operands to advance to the next opcode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001109 it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001110 }
1111 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112 DCHECK(!is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001113}
1114
1115
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001116int OptimizedFrame::LookupExceptionHandlerInTable(
1117 int* stack_slots, HandlerTable::CatchPrediction* prediction) {
1118 Code* code = LookupCode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001119 HandlerTable* table = HandlerTable::cast(code->handler_table());
1120 int pc_offset = static_cast<int>(pc() - code->entry());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001121 if (stack_slots) *stack_slots = code->stack_slots();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001122 return table->LookupReturn(pc_offset, prediction);
1123}
1124
1125
Ben Murdochb0fe1622011-05-05 13:52:32 +01001126DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001127 int* deopt_index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001128 DCHECK(is_optimized());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001129
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001130 JSFunction* opt_function = function();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001131 Code* code = opt_function->code();
1132
1133 // The code object may have been replaced by lazy deoptimization. Fall
1134 // back to a slow search in this case to find the original optimized
1135 // code object.
1136 if (!code->contains(pc())) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001137 code = isolate()->inner_pointer_to_code_cache()->
1138 GcSafeFindCodeForInnerPointer(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001139 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001140 DCHECK(code != NULL);
1141 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001142
Ben Murdochb8e0da22011-05-16 14:20:40 +01001143 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1144 *deopt_index = safepoint_entry.deoptimization_index();
Ben Murdochc5610432016-08-08 18:44:38 +01001145 if (*deopt_index != Safepoint::kNoDeoptimizationIndex) {
1146 return DeoptimizationInputData::cast(code->deoptimization_data());
1147 }
1148 return nullptr;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001149}
1150
1151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001152void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001153 DCHECK(functions->length() == 0);
1154 DCHECK(is_optimized());
1155
1156 // Delegate to JS frame in absence of turbofan deoptimization.
1157 // TODO(turbofan): Revisit once we support deoptimization across the board.
Ben Murdochda12d292016-06-02 14:46:10 +01001158 Code* code = LookupCode();
1159 if (code->kind() == Code::BUILTIN ||
1160 CannotDeoptFromAsmCode(code, function())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161 return JavaScriptFrame::GetFunctions(functions);
1162 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +01001165 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001166 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
Ben Murdochc5610432016-08-08 18:44:38 +01001167 DCHECK_NOT_NULL(data);
1168 DCHECK_NE(Safepoint::kNoDeoptimizationIndex, deopt_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001169 FixedArray* const literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001170
1171 TranslationIterator it(data->TranslationByteArray(),
1172 data->TranslationIndex(deopt_index)->value());
1173 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001174 DCHECK_EQ(Translation::BEGIN, opcode);
1175 it.Next(); // Skip frame count.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001176 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001177
1178 // We insert the frames in reverse order because the frames
1179 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001180 while (jsframe_count != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001181 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001182 // Skip over operands to advance to the next opcode.
1183 it.Skip(Translation::NumberOfOperandsFor(opcode));
1184 if (opcode == Translation::JS_FRAME ||
1185 opcode == Translation::INTERPRETED_FRAME) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001186 jsframe_count--;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187
1188 // The translation commands are ordered and the function is always at the
1189 // first position.
1190 opcode = static_cast<Translation::Opcode>(it.Next());
1191
1192 // Get the correct function in the optimized frame.
1193 Object* function;
1194 if (opcode == Translation::LITERAL) {
1195 function = literal_array->get(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001197 CHECK_EQ(Translation::STACK_SLOT, opcode);
1198 function = StackSlotAt(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001199 }
1200 functions->Add(JSFunction::cast(function));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001201 }
1202 }
1203}
1204
1205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) {
1207 return StandardFrameConstants::kCallerSPOffset -
1208 ((slot_index + 1) * kPointerSize);
1209}
1210
1211
1212Object* OptimizedFrame::StackSlotAt(int index) const {
1213 return Memory::Object_at(fp() + StackSlotOffsetRelativeToFp(index));
1214}
1215
Ben Murdoch097c5b22016-05-18 11:27:45 +01001216int InterpretedFrame::LookupExceptionHandlerInTable(
1217 int* context_register, HandlerTable::CatchPrediction* prediction) {
1218 BytecodeArray* bytecode = function()->shared()->bytecode_array();
1219 HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
1220 int pc_offset = GetBytecodeOffset() + 1; // Point after current bytecode.
1221 return table->LookupRange(pc_offset, context_register, prediction);
1222}
1223
1224int InterpretedFrame::GetBytecodeOffset() const {
1225 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1226 DCHECK_EQ(
1227 InterpreterFrameConstants::kBytecodeOffsetFromFp,
1228 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1229 int raw_offset = Smi::cast(GetExpression(index))->value();
1230 return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
1231}
1232
1233void InterpretedFrame::PatchBytecodeOffset(int new_offset) {
1234 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1235 DCHECK_EQ(
1236 InterpreterFrameConstants::kBytecodeOffsetFromFp,
1237 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1238 int raw_offset = new_offset + BytecodeArray::kHeaderSize - kHeapObjectTag;
1239 SetExpression(index, Smi::FromInt(raw_offset));
1240}
1241
Ben Murdochc5610432016-08-08 18:44:38 +01001242BytecodeArray* InterpretedFrame::GetBytecodeArray() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001243 const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1244 DCHECK_EQ(
1245 InterpreterFrameConstants::kBytecodeArrayFromFp,
1246 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
Ben Murdochc5610432016-08-08 18:44:38 +01001247 return BytecodeArray::cast(GetExpression(index));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001248}
1249
Ben Murdochc5610432016-08-08 18:44:38 +01001250void InterpretedFrame::PatchBytecodeArray(BytecodeArray* bytecode_array) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001251 const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1252 DCHECK_EQ(
1253 InterpreterFrameConstants::kBytecodeArrayFromFp,
1254 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1255 SetExpression(index, bytecode_array);
1256}
1257
Ben Murdochc5610432016-08-08 18:44:38 +01001258Object* InterpretedFrame::ReadInterpreterRegister(int register_index) const {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001259 const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1260 DCHECK_EQ(
Ben Murdochc5610432016-08-08 18:44:38 +01001261 InterpreterFrameConstants::kRegisterFileFromFp,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001262 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1263 return GetExpression(index + register_index);
1264}
1265
Ben Murdochc5610432016-08-08 18:44:38 +01001266void InterpretedFrame::WriteInterpreterRegister(int register_index,
1267 Object* value) {
1268 const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1269 DCHECK_EQ(
1270 InterpreterFrameConstants::kRegisterFileFromFp,
1271 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1272 return SetExpression(index + register_index, value);
1273}
1274
1275void InterpretedFrame::Summarize(List<FrameSummary>* functions,
1276 FrameSummary::Mode mode) const {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001277 DCHECK(functions->length() == 0);
1278 AbstractCode* abstract_code =
1279 AbstractCode::cast(function()->shared()->bytecode_array());
1280 FrameSummary summary(receiver(), function(), abstract_code,
1281 GetBytecodeOffset(), IsConstructor());
1282 functions->Add(summary);
1283}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001284
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001285int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
1286 return Smi::cast(GetExpression(0))->value();
1287}
1288
1289
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001290Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001291 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001292}
1293
Ben Murdoch097c5b22016-05-18 11:27:45 +01001294int ArgumentsAdaptorFrame::GetLength(Address fp) {
1295 const int offset = ArgumentsAdaptorFrameConstants::kLengthOffset;
1296 return Smi::cast(Memory::Object_at(fp + offset))->value();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001297}
1298
Iain Merrick75681382010-08-19 15:07:18 +01001299Code* ArgumentsAdaptorFrame::unchecked_code() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001300 return isolate()->builtins()->builtin(
Steve Block44f0eee2011-05-26 01:26:41 +01001301 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +00001302}
1303
Ben Murdoch097c5b22016-05-18 11:27:45 +01001304Address InternalFrame::GetCallerStackPointer() const {
1305 // Internal frames have no arguments. The stack pointer of the
1306 // caller is at a fixed offset from the frame pointer.
1307 return fp() + StandardFrameConstants::kCallerSPOffset;
1308}
Steve Blocka7e24c12009-10-30 11:49:00 +00001309
Iain Merrick75681382010-08-19 15:07:18 +01001310Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001311 const int offset = InternalFrameConstants::kCodeOffset;
1312 Object* code = Memory::Object_at(fp() + offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001313 DCHECK(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +01001314 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001315}
1316
1317
1318void StackFrame::PrintIndex(StringStream* accumulator,
1319 PrintMode mode,
1320 int index) {
1321 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1322}
1323
Ben Murdochda12d292016-06-02 14:46:10 +01001324void WasmFrame::Print(StringStream* accumulator, PrintMode mode,
1325 int index) const {
1326 accumulator->Add("wasm frame");
1327}
1328
1329Code* WasmFrame::unchecked_code() const {
1330 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
1331}
1332
1333void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); }
1334
1335Address WasmFrame::GetCallerStackPointer() const {
1336 return fp() + ExitFrameConstants::kCallerSPOffset;
1337}
Steve Blocka7e24c12009-10-30 11:49:00 +00001338
Ben Murdochc5610432016-08-08 18:44:38 +01001339Object* WasmFrame::wasm_obj() {
1340 FixedArray* deopt_data = LookupCode()->deoptimization_data();
1341 DCHECK(deopt_data->length() == 2);
1342 return deopt_data->get(0);
1343}
1344
1345uint32_t WasmFrame::function_index() {
1346 FixedArray* deopt_data = LookupCode()->deoptimization_data();
1347 DCHECK(deopt_data->length() == 2);
1348 Object* func_index_obj = deopt_data->get(1);
1349 if (func_index_obj->IsUndefined()) return static_cast<uint32_t>(-1);
1350 if (func_index_obj->IsSmi()) return Smi::cast(func_index_obj)->value();
1351 DCHECK(func_index_obj->IsHeapNumber());
1352 uint32_t val = static_cast<uint32_t>(-1);
1353 func_index_obj->ToUint32(&val);
1354 DCHECK(val != static_cast<uint32_t>(-1));
1355 return val;
1356}
1357
1358Object* WasmFrame::function_name() {
1359 Object* wasm_object = wasm_obj();
1360 if (wasm_object->IsUndefined()) return wasm_object;
1361 Handle<JSObject> wasm = handle(JSObject::cast(wasm_object));
1362 return *wasm::GetWasmFunctionName(wasm, function_index());
1363}
1364
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001365namespace {
1366
1367
1368void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared,
1369 Code* code) {
1370 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1371 std::ostringstream os;
1372 os << "--------- s o u r c e c o d e ---------\n"
1373 << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1374 << "\n-----------------------------------------\n";
1375 accumulator->Add(os.str().c_str());
1376 }
1377}
1378
1379
1380} // namespace
1381
1382
Steve Blocka7e24c12009-10-30 11:49:00 +00001383void JavaScriptFrame::Print(StringStream* accumulator,
1384 PrintMode mode,
1385 int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001386 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001387 Object* receiver = this->receiver();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001388 JSFunction* function = this->function();
Steve Blocka7e24c12009-10-30 11:49:00 +00001389
1390 accumulator->PrintSecurityTokenIfChanged(function);
1391 PrintIndex(accumulator, mode, index);
1392 Code* code = NULL;
1393 if (IsConstructor()) accumulator->Add("new ");
1394 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +01001395
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001396 // Get scope information for nicer output, if possible. If code is NULL, or
1397 // doesn't contain scope info, scope_info will return 0 for the number of
1398 // parameters, stack local variables, context local variables, stack slots,
1399 // or context slots.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001400 SharedFunctionInfo* shared = function->shared();
1401 ScopeInfo* scope_info = shared->scope_info();
1402 Object* script_obj = shared->script();
1403 if (script_obj->IsScript()) {
1404 Script* script = Script::cast(script_obj);
1405 accumulator->Add(" [");
1406 accumulator->PrintName(script->name());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001407
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001408 Address pc = this->pc();
1409 if (code != NULL && code->kind() == Code::FUNCTION &&
1410 pc >= code->instruction_start() && pc < code->instruction_end()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001411 int offset = static_cast<int>(pc - code->instruction_start());
1412 int source_pos = code->SourcePosition(offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001413 int line = script->GetLineNumber(source_pos) + 1;
Ben Murdochc5610432016-08-08 18:44:38 +01001414 accumulator->Add(":%d] [pc=%p]", line, pc);
1415 } else if (is_interpreted()) {
1416 const InterpretedFrame* iframe =
1417 reinterpret_cast<const InterpretedFrame*>(this);
1418 BytecodeArray* bytecodes = iframe->GetBytecodeArray();
1419 int offset = iframe->GetBytecodeOffset();
1420 int source_pos = bytecodes->SourcePosition(offset);
1421 int line = script->GetLineNumber(source_pos) + 1;
1422 accumulator->Add(":%d] [bytecode=%p offset=%d]", line, bytecodes, offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001423 } else {
1424 int function_start_pos = shared->start_position();
1425 int line = script->GetLineNumber(function_start_pos) + 1;
Ben Murdochc5610432016-08-08 18:44:38 +01001426 accumulator->Add(":~%d] [pc=%p]", line, pc);
Steve Block6ded16b2010-05-10 14:33:55 +01001427 }
1428 }
1429
Steve Blocka7e24c12009-10-30 11:49:00 +00001430 accumulator->Add("(this=%o", receiver);
1431
Steve Blocka7e24c12009-10-30 11:49:00 +00001432 // Print the parameters.
1433 int parameters_count = ComputeParametersCount();
1434 for (int i = 0; i < parameters_count; i++) {
1435 accumulator->Add(",");
1436 // If we have a name for the parameter we print it. Nameless
1437 // parameters are either because we have more actual parameters
1438 // than formal parameters or because we have no scope information.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001439 if (i < scope_info->ParameterCount()) {
1440 accumulator->PrintName(scope_info->ParameterName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001441 accumulator->Add("=");
1442 }
1443 accumulator->Add("%o", GetParameter(i));
1444 }
1445
1446 accumulator->Add(")");
1447 if (mode == OVERVIEW) {
1448 accumulator->Add("\n");
1449 return;
1450 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001451 if (is_optimized()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001452 accumulator->Add(" {\n// optimized frame\n");
1453 PrintFunctionSource(accumulator, shared, code);
1454 accumulator->Add("}\n");
Ben Murdoch257744e2011-11-30 15:57:28 +00001455 return;
1456 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001457 accumulator->Add(" {\n");
1458
1459 // Compute the number of locals and expression stack elements.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001460 int stack_locals_count = scope_info->StackLocalCount();
1461 int heap_locals_count = scope_info->ContextLocalCount();
Steve Blocka7e24c12009-10-30 11:49:00 +00001462 int expressions_count = ComputeExpressionsCount();
1463
1464 // Print stack-allocated local variables.
1465 if (stack_locals_count > 0) {
1466 accumulator->Add(" // stack-allocated locals\n");
1467 }
1468 for (int i = 0; i < stack_locals_count; i++) {
1469 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001470 accumulator->PrintName(scope_info->StackLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001471 accumulator->Add(" = ");
1472 if (i < expressions_count) {
1473 accumulator->Add("%o", GetExpression(i));
1474 } else {
1475 accumulator->Add("// no expression found - inconsistent frame?");
1476 }
1477 accumulator->Add("\n");
1478 }
1479
1480 // Try to get hold of the context of this frame.
1481 Context* context = NULL;
1482 if (this->context() != NULL && this->context()->IsContext()) {
1483 context = Context::cast(this->context());
1484 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001485 while (context->IsWithContext()) {
1486 context = context->previous();
1487 DCHECK(context != NULL);
1488 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001489
1490 // Print heap-allocated local variables.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001491 if (heap_locals_count > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001492 accumulator->Add(" // heap-allocated locals\n");
1493 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001494 for (int i = 0; i < heap_locals_count; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001495 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001496 accumulator->PrintName(scope_info->ContextLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001497 accumulator->Add(" = ");
1498 if (context != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 int index = Context::MIN_CONTEXT_SLOTS + i;
1500 if (index < context->length()) {
1501 accumulator->Add("%o", context->get(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00001502 } else {
1503 accumulator->Add(
1504 "// warning: missing context slot - inconsistent frame?");
1505 }
1506 } else {
1507 accumulator->Add("// warning: no context found - inconsistent frame?");
1508 }
1509 accumulator->Add("\n");
1510 }
1511
1512 // Print the expression stack.
1513 int expressions_start = stack_locals_count;
1514 if (expressions_start < expressions_count) {
1515 accumulator->Add(" // expression stack (top to bottom)\n");
1516 }
1517 for (int i = expressions_count - 1; i >= expressions_start; i--) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001518 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1519 }
1520
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001521 PrintFunctionSource(accumulator, shared, code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001522
1523 accumulator->Add("}\n\n");
1524}
1525
1526
1527void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1528 PrintMode mode,
1529 int index) const {
1530 int actual = ComputeParametersCount();
1531 int expected = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001532 JSFunction* function = this->function();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001533 expected = function->shared()->internal_formal_parameter_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00001534
1535 PrintIndex(accumulator, mode, index);
1536 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1537 if (mode == OVERVIEW) {
1538 accumulator->Add("\n");
1539 return;
1540 }
1541 accumulator->Add(" {\n");
1542
1543 // Print actual arguments.
1544 if (actual > 0) accumulator->Add(" // actual arguments\n");
1545 for (int i = 0; i < actual; i++) {
1546 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1547 if (expected != -1 && i >= expected) {
1548 accumulator->Add(" // not passed to callee");
1549 }
1550 accumulator->Add("\n");
1551 }
1552
1553 accumulator->Add("}\n\n");
1554}
1555
1556
1557void EntryFrame::Iterate(ObjectVisitor* v) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001558 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001559}
1560
1561
1562void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001563 const int offset = StandardFrameConstants::kLastObjectOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +00001564 Object** base = &Memory::Object_at(sp());
1565 Object** limit = &Memory::Object_at(fp() + offset) + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00001566 v->VisitPointers(base, limit);
1567}
1568
1569
1570void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1571 IterateExpressions(v);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001572 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001573}
1574
Steve Blocka7e24c12009-10-30 11:49:00 +00001575void InternalFrame::Iterate(ObjectVisitor* v) const {
1576 // Internal frames only have object pointers on the expression stack
1577 // as they never have any arguments.
1578 IterateExpressions(v);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001579 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001580}
1581
1582
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001583void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
1584 Object** base = &Memory::Object_at(sp());
Ben Murdochda12d292016-06-02 14:46:10 +01001585 Object** limit = &Memory::Object_at(
1586 fp() + StubFailureTrampolineFrameConstants::kFixedHeaderBottomOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001587 v->VisitPointers(base, limit);
Ben Murdochda12d292016-06-02 14:46:10 +01001588 base = &Memory::Object_at(fp() + StandardFrameConstants::kFunctionOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001589 const int offset = StandardFrameConstants::kLastObjectOffset;
1590 limit = &Memory::Object_at(fp() + offset) + 1;
1591 v->VisitPointers(base, limit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001592 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001593}
1594
1595
1596Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
1597 return fp() + StandardFrameConstants::kCallerSPOffset;
1598}
1599
1600
1601Code* StubFailureTrampolineFrame::unchecked_code() const {
1602 Code* trampoline;
1603 StubFailureTrampolineStub(isolate(), NOT_JS_FUNCTION_STUB_MODE).
1604 FindCodeInCache(&trampoline);
1605 if (trampoline->contains(pc())) {
1606 return trampoline;
1607 }
1608
1609 StubFailureTrampolineStub(isolate(), JS_FUNCTION_STUB_MODE).
1610 FindCodeInCache(&trampoline);
1611 if (trampoline->contains(pc())) {
1612 return trampoline;
1613 }
1614
1615 UNREACHABLE();
1616 return NULL;
1617}
1618
1619
Steve Blocka7e24c12009-10-30 11:49:00 +00001620// -------------------------------------------------------------------------
1621
1622
1623JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001624 DCHECK(n >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001625 for (int i = 0; i <= n; i++) {
1626 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1627 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1628 iterator_.Advance();
1629 }
1630 UNREACHABLE();
1631 return NULL;
1632}
1633
1634
1635// -------------------------------------------------------------------------
1636
1637
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001638static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1639 MapWord map_word = object->map_word();
1640 return map_word.IsForwardingAddress() ?
1641 map_word.ToForwardingAddress()->map() : map_word.ToMap();
1642}
1643
1644
1645static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1646 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1647}
1648
1649
1650#ifdef DEBUG
1651static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1652 Map* map = GcSafeMapOfCodeSpaceObject(code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001653 DCHECK(map == code->GetHeap()->code_map());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001654 Address start = code->address();
1655 Address end = code->address() + code->SizeFromMap(map);
1656 return start <= addr && addr < end;
1657}
1658#endif
1659
1660
1661Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1662 Address inner_pointer) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001663 Code* code = reinterpret_cast<Code*>(object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001664 DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001665 return code;
1666}
1667
1668
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001669Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1670 Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001671 Heap* heap = isolate_->heap();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001672
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001673 // Check if the inner pointer points into a large object chunk.
1674 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1675 if (large_page != NULL) {
1676 return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1677 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001678
Ben Murdoch097c5b22016-05-18 11:27:45 +01001679 if (!heap->code_space()->Contains(inner_pointer)) {
1680 return nullptr;
1681 }
1682
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001683 // Iterate through the page until we reach the end or find an object starting
1684 // after the inner pointer.
1685 Page* page = Page::FromAddress(inner_pointer);
1686
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001687 DCHECK_EQ(page->owner(), heap->code_space());
Ben Murdochc5610432016-08-08 18:44:38 +01001688 heap->mark_compact_collector()->sweeper().SweepOrWaitUntilSweepingCompleted(
1689 page);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001690
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001691 Address addr = page->skip_list()->StartFor(inner_pointer);
1692
1693 Address top = heap->code_space()->top();
1694 Address limit = heap->code_space()->limit();
1695
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001696 while (true) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001697 if (addr == top && addr != limit) {
1698 addr = limit;
1699 continue;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001700 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001701
1702 HeapObject* obj = HeapObject::FromAddress(addr);
1703 int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1704 Address next_addr = addr + obj_size;
1705 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1706 addr = next_addr;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001707 }
1708}
1709
Ben Murdochb0fe1622011-05-05 13:52:32 +01001710
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001711InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1712 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001713 isolate_->counters()->pc_to_code()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001714 DCHECK(base::bits::IsPowerOfTwo32(kInnerPointerToCodeCacheSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001715 uint32_t hash = ComputeIntegerHash(ObjectAddressForHashing(inner_pointer),
1716 v8::internal::kZeroHashSeed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001717 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1718 InnerPointerToCodeCacheEntry* entry = cache(index);
1719 if (entry->inner_pointer == inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001720 isolate_->counters()->pc_to_code_cached()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001721 DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001722 } else {
1723 // Because this code may be interrupted by a profiling signal that
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001724 // also queries the cache, we cannot update inner_pointer before the code
1725 // has been set. Otherwise, we risk trying to use a cache entry before
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001726 // the code has been computed.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001727 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001728 entry->safepoint_entry.Reset();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001729 entry->inner_pointer = inner_pointer;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001730 }
1731 return entry;
1732}
1733
1734
1735// -------------------------------------------------------------------------
1736
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001737
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001738int NumRegs(RegList reglist) { return base::bits::CountPopulation(reglist); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001739
1740
1741struct JSCallerSavedCodeData {
Steve Block44f0eee2011-05-26 01:26:41 +01001742 int reg_code[kNumJSCallerSaved];
1743};
1744
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001745JSCallerSavedCodeData caller_saved_code_data;
Steve Block44f0eee2011-05-26 01:26:41 +01001746
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001747void SetUpJSCallerSavedCodeData() {
1748 int i = 0;
1749 for (int r = 0; r < kNumRegs; r++)
1750 if ((kJSCallerSaved & (1 << r)) != 0)
1751 caller_saved_code_data.reg_code[i++] = r;
1752
1753 DCHECK(i == kNumJSCallerSaved);
1754}
1755
Steve Block44f0eee2011-05-26 01:26:41 +01001756
1757int JSCallerSavedCode(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001758 DCHECK(0 <= n && n < kNumJSCallerSaved);
1759 return caller_saved_code_data.reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001760}
1761
1762
Steve Block6ded16b2010-05-10 14:33:55 +01001763#define DEFINE_WRAPPER(type, field) \
1764class field##_Wrapper : public ZoneObject { \
1765 public: /* NOLINT */ \
1766 field##_Wrapper(const field& original) : frame_(original) { \
1767 } \
1768 field frame_; \
1769};
1770STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1771#undef DEFINE_WRAPPER
1772
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001773static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
Steve Block6ded16b2010-05-10 14:33:55 +01001774#define FRAME_TYPE_CASE(type, field) \
1775 case StackFrame::type: { \
1776 field##_Wrapper* wrapper = \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001777 new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
Steve Block6ded16b2010-05-10 14:33:55 +01001778 return &wrapper->frame_; \
1779 }
1780
1781 switch (frame->type()) {
1782 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1783 default: UNREACHABLE();
1784 }
1785#undef FRAME_TYPE_CASE
1786 return NULL;
1787}
1788
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001789
1790Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
1791 ZoneList<StackFrame*> list(10, zone);
1792 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1793 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1794 list.Add(frame, zone);
Steve Block6ded16b2010-05-10 14:33:55 +01001795 }
1796 return list.ToVector();
1797}
1798
1799
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001800} // namespace internal
1801} // namespace v8