blob: 698b93541f581beb57497377d1fc2c4c12b6a455 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/frames.h"
6
7#include <sstream>
8
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/ast/ast.h"
10#include "src/ast/scopeinfo.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/base/bits.h"
12#include "src/deoptimizer.h"
13#include "src/frames-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/full-codegen/full-codegen.h"
15#include "src/register-configuration.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016#include "src/safepoint-table.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017#include "src/string-stream.h"
18#include "src/vm-state-inl.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000019
Steve Blocka7e24c12009-10-30 11:49:00 +000020namespace v8 {
21namespace internal {
22
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023ReturnAddressLocationResolver
24 StackFrame::return_address_location_resolver_ = NULL;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010025
26
Steve Blocka7e24c12009-10-30 11:49:00 +000027// Iterator that supports traversing the stack handlers of a
28// particular frame. Needs to know the top of the handler chain.
29class StackHandlerIterator BASE_EMBEDDED {
30 public:
31 StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
32 : limit_(frame->fp()), handler_(handler) {
33 // Make sure the handler has already been unwound to this frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034 DCHECK(frame->sp() <= handler->address());
Steve Blocka7e24c12009-10-30 11:49:00 +000035 }
36
37 StackHandler* handler() const { return handler_; }
38
39 bool done() {
40 return handler_ == NULL || handler_->address() > limit_;
41 }
42 void Advance() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +000044 handler_ = handler_->next();
45 }
46
47 private:
48 const Address limit_;
49 StackHandler* handler_;
50};
51
52
53// -------------------------------------------------------------------------
54
55
56#define INITIALIZE_SINGLETON(type, field) field##_(this),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
58 bool can_access_heap_objects)
Ben Murdoch8b112d22011-06-08 16:22:53 +010059 : isolate_(isolate),
60 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
61 frame_(NULL), handler_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 can_access_heap_objects_(can_access_heap_objects) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010063}
Steve Blocka7e24c12009-10-30 11:49:00 +000064#undef INITIALIZE_SINGLETON
65
66
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067StackFrameIterator::StackFrameIterator(Isolate* isolate)
68 : StackFrameIteratorBase(isolate, true) {
69 Reset(isolate->thread_local_top());
70}
71
72
73StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
74 : StackFrameIteratorBase(isolate, true) {
75 Reset(t);
76}
77
78
79void StackFrameIterator::Advance() {
80 DCHECK(!done());
Steve Blocka7e24c12009-10-30 11:49:00 +000081 // Compute the state of the calling frame before restoring
82 // callee-saved registers and unwinding handlers. This allows the
83 // frame code that computes the caller state to access the top
84 // handler and the value of any callee-saved register if needed.
85 StackFrame::State state;
86 StackFrame::Type type = frame_->GetCallerState(&state);
87
88 // Unwind handlers corresponding to the current frame.
89 StackHandlerIterator it(frame_, handler_);
90 while (!it.done()) it.Advance();
91 handler_ = it.handler();
92
93 // Advance to the calling frame.
94 frame_ = SingletonFor(type, &state);
95
96 // When we're done iterating over the stack frames, the handler
97 // chain must have been completely unwound.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 DCHECK(!done() || handler_ == NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +000099}
100
101
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102void StackFrameIterator::Reset(ThreadLocalTop* top) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 StackFrame::State state;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 StackFrame::Type type = ExitFrame::GetStateForFramePointer(
105 Isolate::c_entry_fp(top), &state);
106 handler_ = StackHandler::FromAddress(Isolate::handler(top));
Steve Blocka7e24c12009-10-30 11:49:00 +0000107 frame_ = SingletonFor(type, &state);
108}
109
110
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
Steve Blocka7e24c12009-10-30 11:49:00 +0000112 StackFrame::State* state) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000113 StackFrame* result = SingletonFor(type);
Ben Murdochc5610432016-08-08 18:44:38 +0100114 DCHECK((!result) == (type == StackFrame::NONE));
115 if (result) result->state_ = *state;
Steve Blocka7e24c12009-10-30 11:49:00 +0000116 return result;
117}
118
119
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000121#define FRAME_TYPE_CASE(type, field) \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100122 case StackFrame::type: \
123 return &field##_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000124
Steve Blocka7e24c12009-10-30 11:49:00 +0000125 switch (type) {
126 case StackFrame::NONE: return NULL;
127 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
128 default: break;
129 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100130 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000131
132#undef FRAME_TYPE_CASE
133}
134
Steve Blocka7e24c12009-10-30 11:49:00 +0000135// -------------------------------------------------------------------------
136
Ben Murdochda12d292016-06-02 14:46:10 +0100137JavaScriptFrameIterator::JavaScriptFrameIterator(Isolate* isolate,
138 StackFrame::Id id)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139 : iterator_(isolate) {
140 while (!done()) {
141 Advance();
142 if (frame()->id() == id) return;
143 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000144}
145
146
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147void JavaScriptFrameIterator::Advance() {
148 do {
149 iterator_.Advance();
150 } while (!iterator_.done() && !iterator_.frame()->is_java_script());
151}
152
153
154void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
155 if (!frame()->has_adapted_arguments()) return;
156 iterator_.Advance();
157 DCHECK(iterator_.frame()->is_arguments_adaptor());
158}
159
160
161// -------------------------------------------------------------------------
162
Ben Murdoch8b112d22011-06-08 16:22:53 +0100163StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
Ben Murdochc5610432016-08-08 18:44:38 +0100164 : iterator_(isolate) {
165 if (!done() && !IsValidFrame(iterator_.frame())) Advance();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100166}
167
168
Steve Blocka7e24c12009-10-30 11:49:00 +0000169void StackTraceFrameIterator::Advance() {
Ben Murdochc5610432016-08-08 18:44:38 +0100170 do {
171 iterator_.Advance();
172 } while (!done() && !IsValidFrame(iterator_.frame()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000173}
174
Ben Murdochc5610432016-08-08 18:44:38 +0100175bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
176 if (frame->is_java_script()) {
177 JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame);
178 if (!jsFrame->function()->IsJSFunction()) return false;
179 Object* script = jsFrame->function()->shared()->script();
Leon Clarke4515c472010-02-03 11:58:03 +0000180 // Don't show functions from native scripts to user.
181 return (script->IsScript() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 Script::TYPE_NATIVE != Script::cast(script)->type());
Ben Murdochc5610432016-08-08 18:44:38 +0100183 }
184 // apart from javascript, only wasm is valid
185 return frame->is_wasm();
Leon Clarke4515c472010-02-03 11:58:03 +0000186}
187
Steve Blocka7e24c12009-10-30 11:49:00 +0000188
189// -------------------------------------------------------------------------
190
191
192SafeStackFrameIterator::SafeStackFrameIterator(
Steve Block44f0eee2011-05-26 01:26:41 +0100193 Isolate* isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 Address fp, Address sp, Address js_entry_sp)
195 : StackFrameIteratorBase(isolate, false),
196 low_bound_(sp),
197 high_bound_(js_entry_sp),
198 top_frame_type_(StackFrame::NONE),
199 external_callback_scope_(isolate->external_callback_scope()) {
200 StackFrame::State state;
201 StackFrame::Type type;
Steve Block44f0eee2011-05-26 01:26:41 +0100202 ThreadLocalTop* top = isolate->thread_local_top();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203 if (IsValidTop(top)) {
204 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
205 top_frame_type_ = type;
206 } else if (IsValidStackAddress(fp)) {
207 DCHECK(fp != NULL);
208 state.fp = fp;
209 state.sp = sp;
210 state.pc_address = StackFrame::ResolveReturnAddressLocation(
211 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
212 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
213 // we check only that kMarkerOffset is within the stack bounds and do
214 // compile time check that kContextOffset slot is pushed on the stack before
215 // kMarkerOffset.
Ben Murdochda12d292016-06-02 14:46:10 +0100216 STATIC_ASSERT(StandardFrameConstants::kFunctionOffset <
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 StandardFrameConstants::kContextOffset);
Ben Murdochda12d292016-06-02 14:46:10 +0100218 Address frame_marker = fp + StandardFrameConstants::kFunctionOffset;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 if (IsValidStackAddress(frame_marker)) {
220 type = StackFrame::ComputeType(this, &state);
221 top_frame_type_ = type;
222 } else {
223 // Mark the frame as JAVA_SCRIPT if we cannot determine its type.
224 // The frame anyways will be skipped.
225 type = StackFrame::JAVA_SCRIPT;
226 // Top frame is incomplete so we cannot reliably determine its type.
227 top_frame_type_ = StackFrame::NONE;
228 }
229 } else {
230 return;
231 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 frame_ = SingletonFor(type, &state);
Ben Murdochc5610432016-08-08 18:44:38 +0100233 if (frame_) Advance();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100234}
235
236
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
238 Address c_entry_fp = Isolate::c_entry_fp(top);
239 if (!IsValidExitFrame(c_entry_fp)) return false;
240 // There should be at least one JS_ENTRY stack handler.
241 Address handler = Isolate::handler(top);
242 if (handler == NULL) return false;
243 // Check that there are no js frames on top of the native frames.
244 return c_entry_fp < handler;
245}
246
247
248void SafeStackFrameIterator::AdvanceOneFrame() {
249 DCHECK(!done());
250 StackFrame* last_frame = frame_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000251 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252 // Before advancing to the next stack frame, perform pointer validity tests.
253 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
254 frame_ = NULL;
255 return;
256 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000257
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258 // Advance to the previous frame.
259 StackFrame::State state;
260 StackFrame::Type type = frame_->GetCallerState(&state);
261 frame_ = SingletonFor(type, &state);
Ben Murdochc5610432016-08-08 18:44:38 +0100262 if (!frame_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000263
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264 // Check that we have actually moved to the previous frame in the stack.
265 if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
266 frame_ = NULL;
267 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000268}
269
270
271bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
272 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
273}
274
275
276bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
277 StackFrame::State state;
278 if (frame->is_entry() || frame->is_entry_construct()) {
279 // See EntryFrame::GetCallerState. It computes the caller FP address
280 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
281 // sure that caller FP address is valid.
282 Address caller_fp = Memory::Address_at(
283 frame->fp() + EntryFrameConstants::kCallerFPOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 if (!IsValidExitFrame(caller_fp)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000285 } else if (frame->is_arguments_adaptor()) {
286 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
287 // the number of arguments is stored on stack as Smi. We need to check
288 // that it really an Smi.
289 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
290 GetExpression(0);
291 if (!number_of_args->IsSmi()) {
292 return false;
293 }
294 }
295 frame->ComputeCallerState(&state);
296 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 SingletonFor(frame->GetCallerState(&state)) != NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000298}
299
300
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
302 if (!IsValidStackAddress(fp)) return false;
303 Address sp = ExitFrame::ComputeStackPointer(fp);
304 if (!IsValidStackAddress(sp)) return false;
305 StackFrame::State state;
306 ExitFrame::FillState(fp, sp, &state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 return *state.pc_address != NULL;
308}
309
310
311void SafeStackFrameIterator::Advance() {
312 while (true) {
313 AdvanceOneFrame();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100314 if (done()) break;
315 ExternalCallbackScope* last_callback_scope = NULL;
316 while (external_callback_scope_ != NULL &&
317 external_callback_scope_->scope_address() < frame_->fp()) {
318 // As long as the setup of a frame is not atomic, we may happen to be
319 // in an interval where an ExternalCallbackScope is already created,
320 // but the frame is not yet entered. So we are actually observing
321 // the previous frame.
322 // Skip all the ExternalCallbackScope's that are below the current fp.
323 last_callback_scope = external_callback_scope_;
324 external_callback_scope_ = external_callback_scope_->previous();
325 }
326 if (frame_->is_java_script()) break;
327 if (frame_->is_exit()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328 // Some of the EXIT frames may have ExternalCallbackScope allocated on
329 // top of them. In that case the scope corresponds to the first EXIT
330 // frame beneath it. There may be other EXIT frames on top of the
331 // ExternalCallbackScope, just skip them as we cannot collect any useful
332 // information about them.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100333 if (last_callback_scope) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334 frame_->state_.pc_address =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100335 last_callback_scope->callback_entrypoint_address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100337 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000339 }
340}
341
342
343// -------------------------------------------------------------------------
344
345
Ben Murdoch8b112d22011-06-08 16:22:53 +0100346Code* StackFrame::GetSafepointData(Isolate* isolate,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100347 Address inner_pointer,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100348 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100349 unsigned* stack_slots) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100350 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
351 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100352 if (!entry->safepoint_entry.is_valid()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100353 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000354 DCHECK(entry->safepoint_entry.is_valid());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100355 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356 DCHECK(entry->safepoint_entry.Equals(
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100357 entry->code->GetSafepointEntry(inner_pointer)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100358 }
359
360 // Fill in the results and return the code.
361 Code* code = entry->code;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100362 *safepoint_entry = entry->safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100363 *stack_slots = code->stack_slots();
364 return code;
365}
366
367
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100368#ifdef DEBUG
369static bool GcSafeCodeContains(HeapObject* object, Address addr);
370#endif
371
372
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373void StackFrame::IteratePc(ObjectVisitor* v, Address* pc_address,
374 Address* constant_pool_address, Code* holder) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100375 Address pc = *pc_address;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000376 DCHECK(GcSafeCodeContains(holder, pc));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100377 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
378 Object* code = holder;
379 v->VisitPointer(&code);
380 if (code != holder) {
381 holder = reinterpret_cast<Code*>(code);
382 pc = holder->instruction_start() + pc_offset;
383 *pc_address = pc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384 if (FLAG_enable_embedded_constant_pool && constant_pool_address) {
385 *constant_pool_address = holder->constant_pool();
386 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000387 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000388}
389
390
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100391void StackFrame::SetReturnAddressLocationResolver(
392 ReturnAddressLocationResolver resolver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000393 DCHECK(return_address_location_resolver_ == NULL);
394 return_address_location_resolver_ = resolver;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100395}
396
Ben Murdochda12d292016-06-02 14:46:10 +0100397static bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
398 Code* interpreter_entry_trampoline =
399 isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
400 Code* interpreter_bytecode_dispatch =
401 isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100402 Code* interpreter_baseline_on_return =
403 isolate->builtins()->builtin(Builtins::kInterpreterMarkBaselineOnReturn);
Ben Murdochda12d292016-06-02 14:46:10 +0100404
405 return (pc >= interpreter_entry_trampoline->instruction_start() &&
406 pc < interpreter_entry_trampoline->instruction_end()) ||
407 (pc >= interpreter_bytecode_dispatch->instruction_start() &&
Ben Murdoch61f157c2016-09-16 13:49:30 +0100408 pc < interpreter_bytecode_dispatch->instruction_end()) ||
409 (pc >= interpreter_baseline_on_return->instruction_start() &&
410 pc < interpreter_baseline_on_return->instruction_end());
Ben Murdochda12d292016-06-02 14:46:10 +0100411}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100412
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
414 State* state) {
415 DCHECK(state->fp != NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416
Ben Murdochda12d292016-06-02 14:46:10 +0100417#if defined(USE_SIMULATOR)
418 MSAN_MEMORY_IS_INITIALIZED(
419 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset,
420 kPointerSize);
421#endif
422 Object* marker = Memory::Object_at(
423 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000424 if (!iterator->can_access_heap_objects_) {
425 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really
426 // means that we are being called from the profiler, which can interrupt
427 // the VM with a signal at any arbitrary instruction, with essentially
428 // anything on the stack. So basically none of these checks are 100%
429 // reliable.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100430#if defined(USE_SIMULATOR)
431 MSAN_MEMORY_IS_INITIALIZED(
Ben Murdochda12d292016-06-02 14:46:10 +0100432 state->fp + StandardFrameConstants::kFunctionOffset, kPointerSize);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100433#endif
Ben Murdochda12d292016-06-02 14:46:10 +0100434 Object* maybe_function =
435 Memory::Object_at(state->fp + StandardFrameConstants::kFunctionOffset);
436 if (!marker->IsSmi()) {
437 if (maybe_function->IsSmi()) {
438 return NONE;
439 } else if (FLAG_ignition && IsInterpreterFramePc(iterator->isolate(),
440 *(state->pc_address))) {
441 return INTERPRETED;
442 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000443 return JAVA_SCRIPT;
Ben Murdochda12d292016-06-02 14:46:10 +0100444 }
445 }
446 } else {
447 // Look up the code object to figure out the type of the stack frame.
448 Code* code_obj =
449 GetContainingCode(iterator->isolate(), *(state->pc_address));
450 if (code_obj != nullptr) {
Ben Murdochda12d292016-06-02 14:46:10 +0100451 switch (code_obj->kind()) {
452 case Code::BUILTIN:
453 if (marker->IsSmi()) break;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100454 if (code_obj->is_interpreter_trampoline_builtin()) {
455 return INTERPRETED;
456 }
457 if (code_obj->is_turbofanned()) {
458 // TODO(bmeurer): We treat frames for BUILTIN Code objects as
459 // OptimizedFrame for now (all the builtins with JavaScript
460 // linkage are actually generated with TurboFan currently, so
461 // this is sound).
462 return OPTIMIZED;
463 }
464 return BUILTIN;
Ben Murdochda12d292016-06-02 14:46:10 +0100465 case Code::FUNCTION:
466 return JAVA_SCRIPT;
467 case Code::OPTIMIZED_FUNCTION:
468 return OPTIMIZED;
469 case Code::WASM_FUNCTION:
470 return WASM;
471 case Code::WASM_TO_JS_FUNCTION:
472 return WASM_TO_JS;
473 case Code::JS_TO_WASM_FUNCTION:
474 return JS_TO_WASM;
475 default:
476 // All other types should have an explicit marker
477 break;
478 }
479 } else {
480 return NONE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000481 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100482 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483
Ben Murdochda12d292016-06-02 14:46:10 +0100484 DCHECK(marker->IsSmi());
485 StackFrame::Type candidate =
486 static_cast<StackFrame::Type>(Smi::cast(marker)->value());
487 switch (candidate) {
488 case ENTRY:
489 case ENTRY_CONSTRUCT:
490 case EXIT:
491 case STUB:
492 case STUB_FAILURE_TRAMPOLINE:
493 case INTERNAL:
494 case CONSTRUCT:
495 case ARGUMENTS_ADAPTOR:
Ben Murdochda12d292016-06-02 14:46:10 +0100496 case WASM_TO_JS:
497 case WASM:
Ben Murdochc5610432016-08-08 18:44:38 +0100498 return candidate;
499 case JS_TO_WASM:
Ben Murdochda12d292016-06-02 14:46:10 +0100500 case JAVA_SCRIPT:
501 case OPTIMIZED:
502 case INTERPRETED:
503 default:
504 // Unoptimized and optimized JavaScript frames, including
505 // interpreted frames, should never have a StackFrame::Type
506 // marker. If we find one, we're likely being called from the
507 // profiler in a bogus stack frame.
508 return NONE;
509 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000510}
511
512
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000513#ifdef DEBUG
514bool StackFrame::can_access_heap_objects() const {
515 return iterator_->can_access_heap_objects_;
516}
517#endif
518
Steve Blocka7e24c12009-10-30 11:49:00 +0000519
520StackFrame::Type StackFrame::GetCallerState(State* state) const {
521 ComputeCallerState(state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522 return ComputeType(iterator_, state);
523}
524
525
526Address StackFrame::UnpaddedFP() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000527 return fp();
Steve Blocka7e24c12009-10-30 11:49:00 +0000528}
529
530
Iain Merrick75681382010-08-19 15:07:18 +0100531Code* EntryFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 return isolate()->heap()->js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000533}
534
535
536void EntryFrame::ComputeCallerState(State* state) const {
537 GetCallerState(state);
538}
539
540
Steve Block6ded16b2010-05-10 14:33:55 +0100541void EntryFrame::SetCallerFp(Address caller_fp) {
542 const int offset = EntryFrameConstants::kCallerFPOffset;
543 Memory::Address_at(this->fp() + offset) = caller_fp;
544}
545
546
Steve Blocka7e24c12009-10-30 11:49:00 +0000547StackFrame::Type EntryFrame::GetCallerState(State* state) const {
548 const int offset = EntryFrameConstants::kCallerFPOffset;
549 Address fp = Memory::Address_at(this->fp() + offset);
550 return ExitFrame::GetStateForFramePointer(fp, state);
551}
552
553
Iain Merrick75681382010-08-19 15:07:18 +0100554Code* EntryConstructFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 return isolate()->heap()->js_construct_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000556}
557
558
Steve Blockd0582a62009-12-15 09:54:21 +0000559Object*& ExitFrame::code_slot() const {
560 const int offset = ExitFrameConstants::kCodeOffset;
561 return Memory::Object_at(fp() + offset);
562}
563
564
Iain Merrick75681382010-08-19 15:07:18 +0100565Code* ExitFrame::unchecked_code() const {
566 return reinterpret_cast<Code*>(code_slot());
Steve Blocka7e24c12009-10-30 11:49:00 +0000567}
568
569
570void ExitFrame::ComputeCallerState(State* state) const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100571 // Set up the caller state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000572 state->sp = caller_sp();
573 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100574 state->pc_address = ResolveReturnAddressLocation(
575 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 if (FLAG_enable_embedded_constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000577 state->constant_pool_address = reinterpret_cast<Address*>(
578 fp() + ExitFrameConstants::kConstantPoolOffset);
579 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000580}
581
582
Steve Block6ded16b2010-05-10 14:33:55 +0100583void ExitFrame::SetCallerFp(Address caller_fp) {
584 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
585}
586
587
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100588void ExitFrame::Iterate(ObjectVisitor* v) const {
589 // The arguments are traversed as part of the expression stack of
590 // the calling frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100592 v->VisitPointer(&code_slot());
593}
594
595
Steve Blocka7e24c12009-10-30 11:49:00 +0000596Address ExitFrame::GetCallerStackPointer() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100597 return fp() + ExitFrameConstants::kCallerSPOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +0000598}
599
600
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100601StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
602 if (fp == 0) return NONE;
603 Address sp = ComputeStackPointer(fp);
604 FillState(fp, sp, state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 DCHECK(*state->pc_address != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100606 return EXIT;
607}
608
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609Address ExitFrame::ComputeStackPointer(Address fp) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100610#if defined(USE_SIMULATOR)
611 MSAN_MEMORY_IS_INITIALIZED(fp + ExitFrameConstants::kSPOffset, kPointerSize);
612#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000613 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
614}
615
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100616void ExitFrame::FillState(Address fp, Address sp, State* state) {
617 state->sp = sp;
618 state->fp = fp;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100619 state->pc_address = ResolveReturnAddressLocation(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621 // The constant pool recorded in the exit frame is not associated
622 // with the pc in this state (the return address into a C entry
623 // stub). ComputeCallerState will retrieve the constant pool
624 // together with the associated caller pc.
625 state->constant_pool_address = NULL;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100626}
627
Steve Blocka7e24c12009-10-30 11:49:00 +0000628Address StandardFrame::GetExpressionAddress(int n) const {
629 const int offset = StandardFrameConstants::kExpressionsOffset;
630 return fp() + offset - n * kPointerSize;
631}
632
Ben Murdoch097c5b22016-05-18 11:27:45 +0100633Address InterpretedFrame::GetExpressionAddress(int n) const {
634 const int offset = InterpreterFrameConstants::kExpressionsOffset;
635 return fp() + offset - n * kPointerSize;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000636}
637
Steve Blocka7e24c12009-10-30 11:49:00 +0000638int StandardFrame::ComputeExpressionsCount() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100639 Address base = GetExpressionAddress(0);
640 Address limit = sp() - kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641 DCHECK(base >= limit); // stack grows downwards
Steve Blocka7e24c12009-10-30 11:49:00 +0000642 // Include register-allocated locals in number of expressions.
Steve Blockd0582a62009-12-15 09:54:21 +0000643 return static_cast<int>((base - limit) / kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000644}
645
646
647void StandardFrame::ComputeCallerState(State* state) const {
648 state->sp = caller_sp();
649 state->fp = caller_fp();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100650 state->pc_address = ResolveReturnAddressLocation(
651 reinterpret_cast<Address*>(ComputePCAddress(fp())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 state->constant_pool_address =
653 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000654}
655
656
Steve Block6ded16b2010-05-10 14:33:55 +0100657void StandardFrame::SetCallerFp(Address caller_fp) {
658 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
659 caller_fp;
660}
661
662
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000663void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100664 // Make sure that we're not doing "safe" stack frame iteration. We cannot
665 // possibly find pointers in optimized frames in that state.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000666 DCHECK(can_access_heap_objects());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100667
668 // Compute the safepoint information.
669 unsigned stack_slots = 0;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100670 SafepointEntry safepoint_entry;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100671 Code* code = StackFrame::GetSafepointData(
Ben Murdoch8b112d22011-06-08 16:22:53 +0100672 isolate(), pc(), &safepoint_entry, &stack_slots);
Ben Murdochda12d292016-06-02 14:46:10 +0100673 unsigned slot_space = stack_slots * kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100674
Ben Murdochda12d292016-06-02 14:46:10 +0100675 // Determine the fixed header and spill slot area size.
676 int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp;
677 Object* marker =
678 Memory::Object_at(fp() + CommonFrameConstants::kContextOrFrameTypeOffset);
679 if (marker->IsSmi()) {
680 StackFrame::Type candidate =
681 static_cast<StackFrame::Type>(Smi::cast(marker)->value());
682 switch (candidate) {
683 case ENTRY:
684 case ENTRY_CONSTRUCT:
685 case EXIT:
686 case STUB_FAILURE_TRAMPOLINE:
687 case ARGUMENTS_ADAPTOR:
688 case STUB:
689 case INTERNAL:
690 case CONSTRUCT:
691 case JS_TO_WASM:
692 case WASM_TO_JS:
693 case WASM:
694 frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
695 break;
696 case JAVA_SCRIPT:
697 case OPTIMIZED:
698 case INTERPRETED:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100699 case BUILTIN:
Ben Murdochda12d292016-06-02 14:46:10 +0100700 // These frame types have a context, but they are actually stored
701 // in the place on the stack that one finds the frame type.
702 UNREACHABLE();
703 break;
704 case NONE:
705 case NUMBER_OF_TYPES:
706 case MANUAL:
707 UNREACHABLE();
708 break;
709 }
710 }
711 slot_space -=
712 (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp);
713
714 Object** frame_header_base = &Memory::Object_at(fp() - frame_header_size);
Ben Murdochc5610432016-08-08 18:44:38 +0100715 Object** frame_header_limit =
716 &Memory::Object_at(fp() - StandardFrameConstants::kCPSlotSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100717 Object** parameters_base = &Memory::Object_at(sp());
Ben Murdochda12d292016-06-02 14:46:10 +0100718 Object** parameters_limit = frame_header_base - slot_space / kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100719
Ben Murdochb8e0da22011-05-16 14:20:40 +0100720 // Visit the parameters that may be on top of the saved registers.
721 if (safepoint_entry.argument_count() > 0) {
722 v->VisitPointers(parameters_base,
723 parameters_base + safepoint_entry.argument_count());
724 parameters_base += safepoint_entry.argument_count();
725 }
726
727 // Skip saved double registers.
728 if (safepoint_entry.has_doubles()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000729 // Number of doubles not known at snapshot time.
730 DCHECK(!isolate()->serializer_enabled());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100731 parameters_base += RegisterConfiguration::Crankshaft()
732 ->num_allocatable_double_registers() *
733 kDoubleSize / kPointerSize;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100734 }
735
Ben Murdochb0fe1622011-05-05 13:52:32 +0100736 // Visit the registers that contain pointers if any.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100737 if (safepoint_entry.HasRegisters()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100738 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100739 if (safepoint_entry.HasRegisterAt(i)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100740 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
741 v->VisitPointer(parameters_base + reg_stack_index);
742 }
743 }
744 // Skip the words containing the register values.
745 parameters_base += kNumSafepointRegisters;
746 }
747
748 // We're done dealing with the register bits.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100749 uint8_t* safepoint_bits = safepoint_entry.bits();
750 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100751
752 // Visit the rest of the parameters.
Ben Murdochda12d292016-06-02 14:46:10 +0100753 if (!is_js_to_wasm() && !is_wasm()) {
754 // Non-WASM frames have tagged values as parameters.
755 v->VisitPointers(parameters_base, parameters_limit);
756 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100757
758 // Visit pointer spill slots and locals.
759 for (unsigned index = 0; index < stack_slots; index++) {
760 int byte_index = index >> kBitsPerByteLog2;
761 int bit_index = index & (kBitsPerByte - 1);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100762 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100763 v->VisitPointer(parameters_limit + index);
764 }
765 }
766
Ben Murdochb0fe1622011-05-05 13:52:32 +0100767 // Visit the return address in the callee and incoming arguments.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000768 IteratePc(v, pc_address(), constant_pool_address(), code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000769
Ben Murdochda12d292016-06-02 14:46:10 +0100770 if (!is_wasm() && !is_wasm_to_js()) {
771 // Visit the context in stub frame and JavaScript frame.
772 // Visit the function in JavaScript frame.
773 v->VisitPointers(frame_header_base, frame_header_limit);
774 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000775}
776
777
778void StubFrame::Iterate(ObjectVisitor* v) const {
779 IterateCompiledFrame(v);
780}
781
782
783Code* StubFrame::unchecked_code() const {
784 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
785}
786
787
788Address StubFrame::GetCallerStackPointer() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100789 return fp() + ExitFrameConstants::kCallerSPOffset;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000790}
791
792
793int StubFrame::GetNumberOfIncomingArguments() const {
794 return 0;
795}
796
797
798void OptimizedFrame::Iterate(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000799 IterateCompiledFrame(v);
800}
801
802
803void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
804 Memory::Object_at(GetParameterSlot(index)) = value;
Steve Blocka7e24c12009-10-30 11:49:00 +0000805}
806
807
808bool JavaScriptFrame::IsConstructor() const {
809 Address fp = caller_fp();
810 if (has_adapted_arguments()) {
811 // Skip the arguments adaptor frame and look at the real caller.
812 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
813 }
814 return IsConstructFrame(fp);
815}
816
817
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000818bool JavaScriptFrame::HasInlinedFrames() const {
819 List<JSFunction*> functions(1);
820 GetFunctions(&functions);
821 return functions.length() > 1;
822}
823
824
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000825int JavaScriptFrame::GetArgumentsLength() const {
826 // If there is an arguments adaptor frame get the arguments length from it.
827 if (has_adapted_arguments()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100828 return ArgumentsAdaptorFrame::GetLength(caller_fp());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000829 } else {
830 return GetNumberOfIncomingArguments();
831 }
832}
833
834
Iain Merrick75681382010-08-19 15:07:18 +0100835Code* JavaScriptFrame::unchecked_code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000836 return function()->code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000837}
838
839
Ben Murdoch8b112d22011-06-08 16:22:53 +0100840int JavaScriptFrame::GetNumberOfIncomingArguments() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 DCHECK(can_access_heap_objects() &&
Ben Murdoch8b112d22011-06-08 16:22:53 +0100842 isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
843
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000844 return function()->shared()->internal_formal_parameter_count();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100845}
846
847
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100848Address JavaScriptFrame::GetCallerStackPointer() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100849 return fp() + StandardFrameConstants::kCallerSPOffset;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100850}
851
852
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000854 DCHECK(functions->length() == 0);
855 functions->Add(function());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100856}
857
Ben Murdochc5610432016-08-08 18:44:38 +0100858void JavaScriptFrame::Summarize(List<FrameSummary>* functions,
859 FrameSummary::Mode mode) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000860 DCHECK(functions->length() == 0);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100861 Code* code = LookupCode();
862 int offset = static_cast<int>(pc() - code->instruction_start());
863 AbstractCode* abstract_code = AbstractCode::cast(code);
864 FrameSummary summary(receiver(), function(), abstract_code, offset,
Ben Murdochc5610432016-08-08 18:44:38 +0100865 IsConstructor(), mode);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100866 functions->Add(summary);
867}
868
Ben Murdochc5610432016-08-08 18:44:38 +0100869JSFunction* JavaScriptFrame::function() const {
870 return JSFunction::cast(function_slot_object());
871}
872
873Object* JavaScriptFrame::receiver() const { return GetParameter(-1); }
874
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000875int JavaScriptFrame::LookupExceptionHandlerInTable(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100876 int* stack_depth, HandlerTable::CatchPrediction* prediction) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000877 Code* code = LookupCode();
878 DCHECK(!code->is_optimized_code());
879 HandlerTable* table = HandlerTable::cast(code->handler_table());
880 int pc_offset = static_cast<int>(pc() - code->entry());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100881 return table->LookupRange(pc_offset, stack_depth, prediction);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000882}
883
884
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
886 Address pc, FILE* file,
887 bool print_line_number) {
888 PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
889 function->PrintName(file);
890 int code_offset = static_cast<int>(pc - code->instruction_start());
891 PrintF(file, "+%d", code_offset);
892 if (print_line_number) {
893 SharedFunctionInfo* shared = function->shared();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100894 int source_pos = code->SourcePosition(code_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895 Object* maybe_script = shared->script();
896 if (maybe_script->IsScript()) {
897 Script* script = Script::cast(maybe_script);
898 int line = script->GetLineNumber(source_pos) + 1;
899 Object* script_name_raw = script->name();
900 if (script_name_raw->IsString()) {
901 String* script_name = String::cast(script->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 base::SmartArrayPointer<char> c_script_name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000903 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
904 PrintF(file, " at %s:%d", c_script_name.get(), line);
905 } else {
906 PrintF(file, " at <unknown>:%d", line);
907 }
908 } else {
909 PrintF(file, " at <unknown>:<unknown>");
910 }
911 }
912}
913
914
915void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100916 bool print_line_number) {
917 // constructor calls
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000918 DisallowHeapAllocation no_allocation;
919 JavaScriptFrameIterator it(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100920 while (!it.done()) {
921 if (it.frame()->is_java_script()) {
922 JavaScriptFrame* frame = it.frame();
923 if (frame->IsConstructor()) PrintF(file, "new ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000924 PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
925 frame->pc(), file, print_line_number);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100926 if (print_args) {
927 // function arguments
928 // (we are intentionally only printing the actually
929 // supplied parameters, not all parameters required)
930 PrintF(file, "(this=");
931 frame->receiver()->ShortPrint(file);
932 const int length = frame->ComputeParametersCount();
933 for (int i = 0; i < length; i++) {
934 PrintF(file, ", ");
935 frame->GetParameter(i)->ShortPrint(file);
936 }
937 PrintF(file, ")");
938 }
939 break;
940 }
941 it.Advance();
942 }
943}
944
945
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000946void JavaScriptFrame::SaveOperandStack(FixedArray* store) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947 int operands_count = store->length();
948 DCHECK_LE(operands_count, ComputeOperandsCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 for (int i = 0; i < operands_count; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950 store->set(i, GetOperand(i));
951 }
952}
953
Ben Murdochda12d292016-06-02 14:46:10 +0100954namespace {
955
956bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) {
957 return code->is_turbofanned() && function->shared()->asm_function() &&
958 !FLAG_turbo_asm_deoptimization;
959}
960
961} // namespace
962
Ben Murdoch097c5b22016-05-18 11:27:45 +0100963FrameSummary::FrameSummary(Object* receiver, JSFunction* function,
964 AbstractCode* abstract_code, int code_offset,
Ben Murdochc5610432016-08-08 18:44:38 +0100965 bool is_constructor, Mode mode)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000966 : receiver_(receiver, function->GetIsolate()),
967 function_(function),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100968 abstract_code_(abstract_code),
969 code_offset_(code_offset),
Ben Murdochda12d292016-06-02 14:46:10 +0100970 is_constructor_(is_constructor) {
971 DCHECK(abstract_code->IsBytecodeArray() ||
972 Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION ||
Ben Murdochc5610432016-08-08 18:44:38 +0100973 CannotDeoptFromAsmCode(Code::cast(abstract_code), function) ||
974 mode == kApproximateSummary);
975}
976
977FrameSummary FrameSummary::GetFirst(JavaScriptFrame* frame) {
978 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
979 frame->Summarize(&frames);
980 return frames.first();
Ben Murdochda12d292016-06-02 14:46:10 +0100981}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000982
Ben Murdochb0fe1622011-05-05 13:52:32 +0100983void FrameSummary::Print() {
984 PrintF("receiver: ");
985 receiver_->ShortPrint();
986 PrintF("\nfunction: ");
987 function_->shared()->DebugName()->ShortPrint();
988 PrintF("\ncode: ");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100989 abstract_code_->ShortPrint();
990 if (abstract_code_->IsCode()) {
991 Code* code = abstract_code_->GetCode();
992 if (code->kind() == Code::FUNCTION) PrintF(" UNOPT ");
Ben Murdochda12d292016-06-02 14:46:10 +0100993 if (code->kind() == Code::OPTIMIZED_FUNCTION) {
Ben Murdochc5610432016-08-08 18:44:38 +0100994 if (function()->shared()->asm_function()) {
995 DCHECK(CannotDeoptFromAsmCode(code, *function()));
996 PrintF(" ASM ");
997 } else {
998 PrintF(" OPT (approximate)");
999 }
Ben Murdochda12d292016-06-02 14:46:10 +01001000 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001001 } else {
1002 PrintF(" BYTECODE ");
1003 }
1004 PrintF("\npc: %d\n", code_offset_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001005}
1006
Ben Murdochc5610432016-08-08 18:44:38 +01001007void OptimizedFrame::Summarize(List<FrameSummary>* frames,
1008 FrameSummary::Mode mode) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001009 DCHECK(frames->length() == 0);
1010 DCHECK(is_optimized());
1011
1012 // Delegate to JS frame in absence of turbofan deoptimization.
1013 // TODO(turbofan): Revisit once we support deoptimization across the board.
Ben Murdochda12d292016-06-02 14:46:10 +01001014 Code* code = LookupCode();
1015 if (code->kind() == Code::BUILTIN ||
1016 CannotDeoptFromAsmCode(code, function())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001017 return JavaScriptFrame::Summarize(frames);
1018 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001019
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001020 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +01001021 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001022 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
Ben Murdochc5610432016-08-08 18:44:38 +01001023 if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
1024 DCHECK(data == nullptr);
1025 if (mode == FrameSummary::kApproximateSummary) {
1026 return JavaScriptFrame::Summarize(frames, mode);
1027 }
1028 FATAL("Missing deoptimization information for OptimizedFrame::Summarize.");
1029 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001030 FixedArray* const literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001031
1032 TranslationIterator it(data->TranslationByteArray(),
1033 data->TranslationIndex(deopt_index)->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034 Translation::Opcode frame_opcode =
1035 static_cast<Translation::Opcode>(it.Next());
1036 DCHECK_EQ(Translation::BEGIN, frame_opcode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001037 it.Next(); // Drop frame count.
1038 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001039
1040 // We create the summary in reverse order because the frames
1041 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001042 bool is_constructor = IsConstructor();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043 while (jsframe_count != 0) {
1044 frame_opcode = static_cast<Translation::Opcode>(it.Next());
1045 if (frame_opcode == Translation::JS_FRAME ||
1046 frame_opcode == Translation::INTERPRETED_FRAME) {
1047 jsframe_count--;
Ben Murdochda12d292016-06-02 14:46:10 +01001048 BailoutId const bailout_id = BailoutId(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 SharedFunctionInfo* const shared_info =
1050 SharedFunctionInfo::cast(literal_array->get(it.Next()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001051 it.Next(); // Skip height.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001052
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001053 // The translation commands are ordered and the function is always
1054 // at the first position, and the receiver is next.
1055 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
1056
1057 // Get the correct function in the optimized frame.
1058 JSFunction* function;
1059 if (opcode == Translation::LITERAL) {
1060 function = JSFunction::cast(literal_array->get(it.Next()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001061 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001062 CHECK_EQ(opcode, Translation::STACK_SLOT);
1063 function = JSFunction::cast(StackSlotAt(it.Next()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001064 }
1065 DCHECK_EQ(shared_info, function->shared());
1066
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001067 // If we are at a call, the receiver is always in a stack slot.
1068 // Otherwise we are not guaranteed to get the receiver value.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001069 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001070
1071 // Get the correct receiver in the optimized frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 Object* receiver;
Ben Murdoch257744e2011-11-30 15:57:28 +00001073 if (opcode == Translation::LITERAL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001074 receiver = literal_array->get(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001075 } else if (opcode == Translation::STACK_SLOT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001076 receiver = StackSlotAt(it.Next());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077 } else {
1078 // The receiver is not in a stack slot nor in a literal. We give up.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001079 it.Skip(Translation::NumberOfOperandsFor(opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001080 // TODO(3029): Materializing a captured object (or duplicated
1081 // object) is hard, we return undefined for now. This breaks the
1082 // produced stack trace, as constructor frames aren't marked as
1083 // such anymore.
1084 receiver = isolate()->heap()->undefined_value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001085 }
1086
Ben Murdoch097c5b22016-05-18 11:27:45 +01001087 AbstractCode* abstract_code;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001088
Ben Murdoch097c5b22016-05-18 11:27:45 +01001089 unsigned code_offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001090 if (frame_opcode == Translation::JS_FRAME) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001091 Code* code = shared_info->code();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001092 DeoptimizationOutputData* const output_data =
1093 DeoptimizationOutputData::cast(code->deoptimization_data());
1094 unsigned const entry =
Ben Murdochda12d292016-06-02 14:46:10 +01001095 Deoptimizer::GetOutputInfo(output_data, bailout_id, shared_info);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001096 code_offset = FullCodeGenerator::PcField::decode(entry);
1097 abstract_code = AbstractCode::cast(code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001098 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001099 DCHECK_EQ(frame_opcode, Translation::INTERPRETED_FRAME);
Ben Murdochda12d292016-06-02 14:46:10 +01001100 // BailoutId points to the next bytecode in the bytecode aray. Subtract
1101 // 1 to get the end of current bytecode.
1102 code_offset = bailout_id.ToInt() - 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001103 abstract_code = AbstractCode::cast(shared_info->bytecode_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001104 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001105 FrameSummary summary(receiver, function, abstract_code, code_offset,
1106 is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001107 frames->Add(summary);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001108 is_constructor = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001109 } else if (frame_opcode == Translation::CONSTRUCT_STUB_FRAME) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001110 // The next encountered JS_FRAME will be marked as a constructor call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001111 it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112 DCHECK(!is_constructor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001113 is_constructor = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001114 } else {
1115 // Skip over operands to advance to the next opcode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001116 it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001117 }
1118 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001119 DCHECK(!is_constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001120}
1121
1122
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001123int OptimizedFrame::LookupExceptionHandlerInTable(
1124 int* stack_slots, HandlerTable::CatchPrediction* prediction) {
1125 Code* code = LookupCode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001126 HandlerTable* table = HandlerTable::cast(code->handler_table());
1127 int pc_offset = static_cast<int>(pc() - code->entry());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001128 if (stack_slots) *stack_slots = code->stack_slots();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001129 return table->LookupReturn(pc_offset, prediction);
1130}
1131
1132
Ben Murdochb0fe1622011-05-05 13:52:32 +01001133DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001134 int* deopt_index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001135 DCHECK(is_optimized());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001136
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001137 JSFunction* opt_function = function();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001138 Code* code = opt_function->code();
1139
1140 // The code object may have been replaced by lazy deoptimization. Fall
1141 // back to a slow search in this case to find the original optimized
1142 // code object.
1143 if (!code->contains(pc())) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001144 code = isolate()->inner_pointer_to_code_cache()->
1145 GcSafeFindCodeForInnerPointer(pc());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001146 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001147 DCHECK(code != NULL);
1148 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001149
Ben Murdochb8e0da22011-05-16 14:20:40 +01001150 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1151 *deopt_index = safepoint_entry.deoptimization_index();
Ben Murdochc5610432016-08-08 18:44:38 +01001152 if (*deopt_index != Safepoint::kNoDeoptimizationIndex) {
1153 return DeoptimizationInputData::cast(code->deoptimization_data());
1154 }
1155 return nullptr;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001156}
1157
1158
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001159void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001160 DCHECK(functions->length() == 0);
1161 DCHECK(is_optimized());
1162
1163 // Delegate to JS frame in absence of turbofan deoptimization.
1164 // TODO(turbofan): Revisit once we support deoptimization across the board.
Ben Murdochda12d292016-06-02 14:46:10 +01001165 Code* code = LookupCode();
1166 if (code->kind() == Code::BUILTIN ||
1167 CannotDeoptFromAsmCode(code, function())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168 return JavaScriptFrame::GetFunctions(functions);
1169 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001170
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +01001172 int deopt_index = Safepoint::kNoDeoptimizationIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001173 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
Ben Murdochc5610432016-08-08 18:44:38 +01001174 DCHECK_NOT_NULL(data);
1175 DCHECK_NE(Safepoint::kNoDeoptimizationIndex, deopt_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001176 FixedArray* const literal_array = data->LiteralArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001177
1178 TranslationIterator it(data->TranslationByteArray(),
1179 data->TranslationIndex(deopt_index)->value());
1180 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001181 DCHECK_EQ(Translation::BEGIN, opcode);
1182 it.Next(); // Skip frame count.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001183 int jsframe_count = it.Next();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001184
1185 // We insert the frames in reverse order because the frames
1186 // in the deoptimization translation are ordered bottom-to-top.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187 while (jsframe_count != 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001188 opcode = static_cast<Translation::Opcode>(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001189 // Skip over operands to advance to the next opcode.
1190 it.Skip(Translation::NumberOfOperandsFor(opcode));
1191 if (opcode == Translation::JS_FRAME ||
1192 opcode == Translation::INTERPRETED_FRAME) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001193 jsframe_count--;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001194
1195 // The translation commands are ordered and the function is always at the
1196 // first position.
1197 opcode = static_cast<Translation::Opcode>(it.Next());
1198
1199 // Get the correct function in the optimized frame.
1200 Object* function;
1201 if (opcode == Translation::LITERAL) {
1202 function = literal_array->get(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001203 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001204 CHECK_EQ(Translation::STACK_SLOT, opcode);
1205 function = StackSlotAt(it.Next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206 }
1207 functions->Add(JSFunction::cast(function));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001208 }
1209 }
1210}
1211
1212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) {
1214 return StandardFrameConstants::kCallerSPOffset -
1215 ((slot_index + 1) * kPointerSize);
1216}
1217
1218
1219Object* OptimizedFrame::StackSlotAt(int index) const {
1220 return Memory::Object_at(fp() + StackSlotOffsetRelativeToFp(index));
1221}
1222
Ben Murdoch097c5b22016-05-18 11:27:45 +01001223int InterpretedFrame::LookupExceptionHandlerInTable(
1224 int* context_register, HandlerTable::CatchPrediction* prediction) {
1225 BytecodeArray* bytecode = function()->shared()->bytecode_array();
1226 HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
1227 int pc_offset = GetBytecodeOffset() + 1; // Point after current bytecode.
1228 return table->LookupRange(pc_offset, context_register, prediction);
1229}
1230
1231int InterpretedFrame::GetBytecodeOffset() const {
1232 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1233 DCHECK_EQ(
1234 InterpreterFrameConstants::kBytecodeOffsetFromFp,
1235 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1236 int raw_offset = Smi::cast(GetExpression(index))->value();
1237 return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
1238}
1239
1240void InterpretedFrame::PatchBytecodeOffset(int new_offset) {
1241 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1242 DCHECK_EQ(
1243 InterpreterFrameConstants::kBytecodeOffsetFromFp,
1244 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1245 int raw_offset = new_offset + BytecodeArray::kHeaderSize - kHeapObjectTag;
1246 SetExpression(index, Smi::FromInt(raw_offset));
1247}
1248
Ben Murdochc5610432016-08-08 18:44:38 +01001249BytecodeArray* InterpretedFrame::GetBytecodeArray() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001250 const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1251 DCHECK_EQ(
1252 InterpreterFrameConstants::kBytecodeArrayFromFp,
1253 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
Ben Murdochc5610432016-08-08 18:44:38 +01001254 return BytecodeArray::cast(GetExpression(index));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001255}
1256
Ben Murdochc5610432016-08-08 18:44:38 +01001257void InterpretedFrame::PatchBytecodeArray(BytecodeArray* bytecode_array) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001258 const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1259 DCHECK_EQ(
1260 InterpreterFrameConstants::kBytecodeArrayFromFp,
1261 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1262 SetExpression(index, bytecode_array);
1263}
1264
Ben Murdochc5610432016-08-08 18:44:38 +01001265Object* InterpretedFrame::ReadInterpreterRegister(int register_index) const {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001266 const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1267 DCHECK_EQ(
Ben Murdochc5610432016-08-08 18:44:38 +01001268 InterpreterFrameConstants::kRegisterFileFromFp,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001269 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1270 return GetExpression(index + register_index);
1271}
1272
Ben Murdochc5610432016-08-08 18:44:38 +01001273void InterpretedFrame::WriteInterpreterRegister(int register_index,
1274 Object* value) {
1275 const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1276 DCHECK_EQ(
1277 InterpreterFrameConstants::kRegisterFileFromFp,
1278 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1279 return SetExpression(index + register_index, value);
1280}
1281
1282void InterpretedFrame::Summarize(List<FrameSummary>* functions,
1283 FrameSummary::Mode mode) const {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001284 DCHECK(functions->length() == 0);
1285 AbstractCode* abstract_code =
1286 AbstractCode::cast(function()->shared()->bytecode_array());
1287 FrameSummary summary(receiver(), function(), abstract_code,
1288 GetBytecodeOffset(), IsConstructor());
1289 functions->Add(summary);
1290}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001291
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001292int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
1293 return Smi::cast(GetExpression(0))->value();
1294}
1295
Ben Murdoch097c5b22016-05-18 11:27:45 +01001296int ArgumentsAdaptorFrame::GetLength(Address fp) {
1297 const int offset = ArgumentsAdaptorFrameConstants::kLengthOffset;
1298 return Smi::cast(Memory::Object_at(fp + offset))->value();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001299}
1300
Iain Merrick75681382010-08-19 15:07:18 +01001301Code* ArgumentsAdaptorFrame::unchecked_code() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001302 return isolate()->builtins()->builtin(
Steve Block44f0eee2011-05-26 01:26:41 +01001303 Builtins::kArgumentsAdaptorTrampoline);
Steve Blocka7e24c12009-10-30 11:49:00 +00001304}
1305
Ben Murdoch61f157c2016-09-16 13:49:30 +01001306void BuiltinFrame::Print(StringStream* accumulator, PrintMode mode,
1307 int index) const {
1308 // TODO(bmeurer)
1309}
1310
1311int BuiltinFrame::GetNumberOfIncomingArguments() const {
1312 return Smi::cast(GetExpression(0))->value();
1313}
1314
Ben Murdoch097c5b22016-05-18 11:27:45 +01001315Address InternalFrame::GetCallerStackPointer() const {
1316 // Internal frames have no arguments. The stack pointer of the
1317 // caller is at a fixed offset from the frame pointer.
1318 return fp() + StandardFrameConstants::kCallerSPOffset;
1319}
Steve Blocka7e24c12009-10-30 11:49:00 +00001320
Iain Merrick75681382010-08-19 15:07:18 +01001321Code* InternalFrame::unchecked_code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +00001322 const int offset = InternalFrameConstants::kCodeOffset;
1323 Object* code = Memory::Object_at(fp() + offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001324 DCHECK(code != NULL);
Iain Merrick75681382010-08-19 15:07:18 +01001325 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001326}
1327
1328
1329void StackFrame::PrintIndex(StringStream* accumulator,
1330 PrintMode mode,
1331 int index) {
1332 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1333}
1334
Ben Murdochda12d292016-06-02 14:46:10 +01001335void WasmFrame::Print(StringStream* accumulator, PrintMode mode,
1336 int index) const {
1337 accumulator->Add("wasm frame");
1338}
1339
1340Code* WasmFrame::unchecked_code() const {
1341 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
1342}
1343
1344void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); }
1345
1346Address WasmFrame::GetCallerStackPointer() const {
1347 return fp() + ExitFrameConstants::kCallerSPOffset;
1348}
Steve Blocka7e24c12009-10-30 11:49:00 +00001349
Ben Murdochc5610432016-08-08 18:44:38 +01001350Object* WasmFrame::wasm_obj() {
1351 FixedArray* deopt_data = LookupCode()->deoptimization_data();
1352 DCHECK(deopt_data->length() == 2);
1353 return deopt_data->get(0);
1354}
1355
1356uint32_t WasmFrame::function_index() {
1357 FixedArray* deopt_data = LookupCode()->deoptimization_data();
1358 DCHECK(deopt_data->length() == 2);
1359 Object* func_index_obj = deopt_data->get(1);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001360 if (func_index_obj->IsUndefined(isolate())) return static_cast<uint32_t>(-1);
Ben Murdochc5610432016-08-08 18:44:38 +01001361 if (func_index_obj->IsSmi()) return Smi::cast(func_index_obj)->value();
1362 DCHECK(func_index_obj->IsHeapNumber());
1363 uint32_t val = static_cast<uint32_t>(-1);
1364 func_index_obj->ToUint32(&val);
1365 DCHECK(val != static_cast<uint32_t>(-1));
1366 return val;
1367}
1368
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369namespace {
1370
1371
1372void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared,
1373 Code* code) {
1374 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1375 std::ostringstream os;
1376 os << "--------- s o u r c e c o d e ---------\n"
1377 << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1378 << "\n-----------------------------------------\n";
1379 accumulator->Add(os.str().c_str());
1380 }
1381}
1382
1383
1384} // namespace
1385
1386
Steve Blocka7e24c12009-10-30 11:49:00 +00001387void JavaScriptFrame::Print(StringStream* accumulator,
1388 PrintMode mode,
1389 int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001390 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001391 Object* receiver = this->receiver();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392 JSFunction* function = this->function();
Steve Blocka7e24c12009-10-30 11:49:00 +00001393
1394 accumulator->PrintSecurityTokenIfChanged(function);
1395 PrintIndex(accumulator, mode, index);
1396 Code* code = NULL;
1397 if (IsConstructor()) accumulator->Add("new ");
1398 accumulator->PrintFunction(function, receiver, &code);
Steve Block6ded16b2010-05-10 14:33:55 +01001399
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001400 // Get scope information for nicer output, if possible. If code is NULL, or
1401 // doesn't contain scope info, scope_info will return 0 for the number of
1402 // parameters, stack local variables, context local variables, stack slots,
1403 // or context slots.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001404 SharedFunctionInfo* shared = function->shared();
1405 ScopeInfo* scope_info = shared->scope_info();
1406 Object* script_obj = shared->script();
1407 if (script_obj->IsScript()) {
1408 Script* script = Script::cast(script_obj);
1409 accumulator->Add(" [");
1410 accumulator->PrintName(script->name());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001411
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001412 Address pc = this->pc();
1413 if (code != NULL && code->kind() == Code::FUNCTION &&
1414 pc >= code->instruction_start() && pc < code->instruction_end()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001415 int offset = static_cast<int>(pc - code->instruction_start());
1416 int source_pos = code->SourcePosition(offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001417 int line = script->GetLineNumber(source_pos) + 1;
Ben Murdochc5610432016-08-08 18:44:38 +01001418 accumulator->Add(":%d] [pc=%p]", line, pc);
1419 } else if (is_interpreted()) {
1420 const InterpretedFrame* iframe =
1421 reinterpret_cast<const InterpretedFrame*>(this);
1422 BytecodeArray* bytecodes = iframe->GetBytecodeArray();
1423 int offset = iframe->GetBytecodeOffset();
1424 int source_pos = bytecodes->SourcePosition(offset);
1425 int line = script->GetLineNumber(source_pos) + 1;
1426 accumulator->Add(":%d] [bytecode=%p offset=%d]", line, bytecodes, offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001427 } else {
1428 int function_start_pos = shared->start_position();
1429 int line = script->GetLineNumber(function_start_pos) + 1;
Ben Murdochc5610432016-08-08 18:44:38 +01001430 accumulator->Add(":~%d] [pc=%p]", line, pc);
Steve Block6ded16b2010-05-10 14:33:55 +01001431 }
1432 }
1433
Steve Blocka7e24c12009-10-30 11:49:00 +00001434 accumulator->Add("(this=%o", receiver);
1435
Steve Blocka7e24c12009-10-30 11:49:00 +00001436 // Print the parameters.
1437 int parameters_count = ComputeParametersCount();
1438 for (int i = 0; i < parameters_count; i++) {
1439 accumulator->Add(",");
1440 // If we have a name for the parameter we print it. Nameless
1441 // parameters are either because we have more actual parameters
1442 // than formal parameters or because we have no scope information.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001443 if (i < scope_info->ParameterCount()) {
1444 accumulator->PrintName(scope_info->ParameterName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 accumulator->Add("=");
1446 }
1447 accumulator->Add("%o", GetParameter(i));
1448 }
1449
1450 accumulator->Add(")");
1451 if (mode == OVERVIEW) {
1452 accumulator->Add("\n");
1453 return;
1454 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001455 if (is_optimized()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001456 accumulator->Add(" {\n// optimized frame\n");
1457 PrintFunctionSource(accumulator, shared, code);
1458 accumulator->Add("}\n");
Ben Murdoch257744e2011-11-30 15:57:28 +00001459 return;
1460 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001461 accumulator->Add(" {\n");
1462
1463 // Compute the number of locals and expression stack elements.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001464 int stack_locals_count = scope_info->StackLocalCount();
1465 int heap_locals_count = scope_info->ContextLocalCount();
Steve Blocka7e24c12009-10-30 11:49:00 +00001466 int expressions_count = ComputeExpressionsCount();
1467
1468 // Print stack-allocated local variables.
1469 if (stack_locals_count > 0) {
1470 accumulator->Add(" // stack-allocated locals\n");
1471 }
1472 for (int i = 0; i < stack_locals_count; i++) {
1473 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001474 accumulator->PrintName(scope_info->StackLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001475 accumulator->Add(" = ");
1476 if (i < expressions_count) {
1477 accumulator->Add("%o", GetExpression(i));
1478 } else {
1479 accumulator->Add("// no expression found - inconsistent frame?");
1480 }
1481 accumulator->Add("\n");
1482 }
1483
1484 // Try to get hold of the context of this frame.
1485 Context* context = NULL;
1486 if (this->context() != NULL && this->context()->IsContext()) {
1487 context = Context::cast(this->context());
1488 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001489 while (context->IsWithContext()) {
1490 context = context->previous();
1491 DCHECK(context != NULL);
1492 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001493
1494 // Print heap-allocated local variables.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001495 if (heap_locals_count > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001496 accumulator->Add(" // heap-allocated locals\n");
1497 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001498 for (int i = 0; i < heap_locals_count; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001499 accumulator->Add(" var ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001500 accumulator->PrintName(scope_info->ContextLocalName(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00001501 accumulator->Add(" = ");
1502 if (context != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503 int index = Context::MIN_CONTEXT_SLOTS + i;
1504 if (index < context->length()) {
1505 accumulator->Add("%o", context->get(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00001506 } else {
1507 accumulator->Add(
1508 "// warning: missing context slot - inconsistent frame?");
1509 }
1510 } else {
1511 accumulator->Add("// warning: no context found - inconsistent frame?");
1512 }
1513 accumulator->Add("\n");
1514 }
1515
1516 // Print the expression stack.
1517 int expressions_start = stack_locals_count;
1518 if (expressions_start < expressions_count) {
1519 accumulator->Add(" // expression stack (top to bottom)\n");
1520 }
1521 for (int i = expressions_count - 1; i >= expressions_start; i--) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001522 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1523 }
1524
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001525 PrintFunctionSource(accumulator, shared, code);
Steve Blocka7e24c12009-10-30 11:49:00 +00001526
1527 accumulator->Add("}\n\n");
1528}
1529
1530
1531void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1532 PrintMode mode,
1533 int index) const {
1534 int actual = ComputeParametersCount();
1535 int expected = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001536 JSFunction* function = this->function();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001537 expected = function->shared()->internal_formal_parameter_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00001538
1539 PrintIndex(accumulator, mode, index);
1540 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1541 if (mode == OVERVIEW) {
1542 accumulator->Add("\n");
1543 return;
1544 }
1545 accumulator->Add(" {\n");
1546
1547 // Print actual arguments.
1548 if (actual > 0) accumulator->Add(" // actual arguments\n");
1549 for (int i = 0; i < actual; i++) {
1550 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1551 if (expected != -1 && i >= expected) {
1552 accumulator->Add(" // not passed to callee");
1553 }
1554 accumulator->Add("\n");
1555 }
1556
1557 accumulator->Add("}\n\n");
1558}
1559
1560
1561void EntryFrame::Iterate(ObjectVisitor* v) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001562 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001563}
1564
1565
1566void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001567 const int offset = StandardFrameConstants::kLastObjectOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +00001568 Object** base = &Memory::Object_at(sp());
1569 Object** limit = &Memory::Object_at(fp() + offset) + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00001570 v->VisitPointers(base, limit);
1571}
1572
1573
1574void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1575 IterateExpressions(v);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001576 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001577}
1578
Steve Blocka7e24c12009-10-30 11:49:00 +00001579void InternalFrame::Iterate(ObjectVisitor* v) const {
1580 // Internal frames only have object pointers on the expression stack
1581 // as they never have any arguments.
1582 IterateExpressions(v);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001583 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Steve Blocka7e24c12009-10-30 11:49:00 +00001584}
1585
1586
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001587void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
1588 Object** base = &Memory::Object_at(sp());
Ben Murdochda12d292016-06-02 14:46:10 +01001589 Object** limit = &Memory::Object_at(
1590 fp() + StubFailureTrampolineFrameConstants::kFixedHeaderBottomOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001591 v->VisitPointers(base, limit);
Ben Murdochda12d292016-06-02 14:46:10 +01001592 base = &Memory::Object_at(fp() + StandardFrameConstants::kFunctionOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001593 const int offset = StandardFrameConstants::kLastObjectOffset;
1594 limit = &Memory::Object_at(fp() + offset) + 1;
1595 v->VisitPointers(base, limit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001596 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001597}
1598
1599
1600Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
1601 return fp() + StandardFrameConstants::kCallerSPOffset;
1602}
1603
1604
1605Code* StubFailureTrampolineFrame::unchecked_code() const {
1606 Code* trampoline;
1607 StubFailureTrampolineStub(isolate(), NOT_JS_FUNCTION_STUB_MODE).
1608 FindCodeInCache(&trampoline);
1609 if (trampoline->contains(pc())) {
1610 return trampoline;
1611 }
1612
1613 StubFailureTrampolineStub(isolate(), JS_FUNCTION_STUB_MODE).
1614 FindCodeInCache(&trampoline);
1615 if (trampoline->contains(pc())) {
1616 return trampoline;
1617 }
1618
1619 UNREACHABLE();
1620 return NULL;
1621}
1622
1623
Steve Blocka7e24c12009-10-30 11:49:00 +00001624// -------------------------------------------------------------------------
1625
1626
1627JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001628 DCHECK(n >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001629 for (int i = 0; i <= n; i++) {
1630 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1631 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1632 iterator_.Advance();
1633 }
1634 UNREACHABLE();
1635 return NULL;
1636}
1637
1638
1639// -------------------------------------------------------------------------
1640
1641
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001642static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1643 MapWord map_word = object->map_word();
1644 return map_word.IsForwardingAddress() ?
1645 map_word.ToForwardingAddress()->map() : map_word.ToMap();
1646}
1647
1648
1649static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1650 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1651}
1652
1653
1654#ifdef DEBUG
1655static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1656 Map* map = GcSafeMapOfCodeSpaceObject(code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001657 DCHECK(map == code->GetHeap()->code_map());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001658 Address start = code->address();
1659 Address end = code->address() + code->SizeFromMap(map);
1660 return start <= addr && addr < end;
1661}
1662#endif
1663
1664
1665Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1666 Address inner_pointer) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001667 Code* code = reinterpret_cast<Code*>(object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001668 DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001669 return code;
1670}
1671
1672
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001673Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1674 Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001675 Heap* heap = isolate_->heap();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001676
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001677 // Check if the inner pointer points into a large object chunk.
1678 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1679 if (large_page != NULL) {
1680 return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1681 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001682
Ben Murdoch097c5b22016-05-18 11:27:45 +01001683 if (!heap->code_space()->Contains(inner_pointer)) {
1684 return nullptr;
1685 }
1686
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001687 // Iterate through the page until we reach the end or find an object starting
1688 // after the inner pointer.
1689 Page* page = Page::FromAddress(inner_pointer);
1690
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001691 DCHECK_EQ(page->owner(), heap->code_space());
Ben Murdochc5610432016-08-08 18:44:38 +01001692 heap->mark_compact_collector()->sweeper().SweepOrWaitUntilSweepingCompleted(
1693 page);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001694
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001695 Address addr = page->skip_list()->StartFor(inner_pointer);
1696
1697 Address top = heap->code_space()->top();
1698 Address limit = heap->code_space()->limit();
1699
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001700 while (true) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001701 if (addr == top && addr != limit) {
1702 addr = limit;
1703 continue;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001704 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001705
1706 HeapObject* obj = HeapObject::FromAddress(addr);
1707 int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1708 Address next_addr = addr + obj_size;
1709 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1710 addr = next_addr;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001711 }
1712}
1713
Ben Murdochb0fe1622011-05-05 13:52:32 +01001714
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001715InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1716 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001717 isolate_->counters()->pc_to_code()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001718 DCHECK(base::bits::IsPowerOfTwo32(kInnerPointerToCodeCacheSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001719 uint32_t hash = ComputeIntegerHash(ObjectAddressForHashing(inner_pointer),
1720 v8::internal::kZeroHashSeed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001721 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1722 InnerPointerToCodeCacheEntry* entry = cache(index);
1723 if (entry->inner_pointer == inner_pointer) {
Steve Block44f0eee2011-05-26 01:26:41 +01001724 isolate_->counters()->pc_to_code_cached()->Increment();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001725 DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001726 } else {
1727 // Because this code may be interrupted by a profiling signal that
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001728 // also queries the cache, we cannot update inner_pointer before the code
1729 // has been set. Otherwise, we risk trying to use a cache entry before
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001730 // the code has been computed.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001731 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001732 entry->safepoint_entry.Reset();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001733 entry->inner_pointer = inner_pointer;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001734 }
1735 return entry;
1736}
1737
1738
1739// -------------------------------------------------------------------------
1740
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001741
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001742int NumRegs(RegList reglist) { return base::bits::CountPopulation(reglist); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001743
1744
1745struct JSCallerSavedCodeData {
Steve Block44f0eee2011-05-26 01:26:41 +01001746 int reg_code[kNumJSCallerSaved];
1747};
1748
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001749JSCallerSavedCodeData caller_saved_code_data;
Steve Block44f0eee2011-05-26 01:26:41 +01001750
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001751void SetUpJSCallerSavedCodeData() {
1752 int i = 0;
1753 for (int r = 0; r < kNumRegs; r++)
1754 if ((kJSCallerSaved & (1 << r)) != 0)
1755 caller_saved_code_data.reg_code[i++] = r;
1756
1757 DCHECK(i == kNumJSCallerSaved);
1758}
1759
Steve Block44f0eee2011-05-26 01:26:41 +01001760
1761int JSCallerSavedCode(int n) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001762 DCHECK(0 <= n && n < kNumJSCallerSaved);
1763 return caller_saved_code_data.reg_code[n];
Steve Blocka7e24c12009-10-30 11:49:00 +00001764}
1765
1766
Steve Block6ded16b2010-05-10 14:33:55 +01001767#define DEFINE_WRAPPER(type, field) \
1768class field##_Wrapper : public ZoneObject { \
1769 public: /* NOLINT */ \
1770 field##_Wrapper(const field& original) : frame_(original) { \
1771 } \
1772 field frame_; \
1773};
1774STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1775#undef DEFINE_WRAPPER
1776
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001777static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
Steve Block6ded16b2010-05-10 14:33:55 +01001778#define FRAME_TYPE_CASE(type, field) \
1779 case StackFrame::type: { \
1780 field##_Wrapper* wrapper = \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001781 new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
Steve Block6ded16b2010-05-10 14:33:55 +01001782 return &wrapper->frame_; \
1783 }
1784
1785 switch (frame->type()) {
1786 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1787 default: UNREACHABLE();
1788 }
1789#undef FRAME_TYPE_CASE
1790 return NULL;
1791}
1792
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001793
1794Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
1795 ZoneList<StackFrame*> list(10, zone);
1796 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1797 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1798 list.Add(frame, zone);
Steve Block6ded16b2010-05-10 14:33:55 +01001799 }
1800 return list.ToVector();
1801}
1802
1803
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001804} // namespace internal
1805} // namespace v8