OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/frames.h" | 5 #include "src/frames.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 } | 175 } |
176 | 176 |
177 void StackTraceFrameIterator::AdvanceToArgumentsFrame() { | 177 void StackTraceFrameIterator::AdvanceToArgumentsFrame() { |
178 if (!is_javascript() || !javascript_frame()->has_adapted_arguments()) return; | 178 if (!is_javascript() || !javascript_frame()->has_adapted_arguments()) return; |
179 iterator_.Advance(); | 179 iterator_.Advance(); |
180 DCHECK(iterator_.frame()->is_arguments_adaptor()); | 180 DCHECK(iterator_.frame()->is_arguments_adaptor()); |
181 } | 181 } |
182 | 182 |
183 // ------------------------------------------------------------------------- | 183 // ------------------------------------------------------------------------- |
184 | 184 |
| 185 namespace { |
| 186 |
| 187 bool IsInterpreterFramePc(Isolate* isolate, Address pc) { |
| 188 Code* interpreter_entry_trampoline = |
| 189 isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline); |
| 190 Code* interpreter_bytecode_advance = |
| 191 isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeAdvance); |
| 192 Code* interpreter_bytecode_dispatch = |
| 193 isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch); |
| 194 |
| 195 return (pc >= interpreter_entry_trampoline->instruction_start() && |
| 196 pc < interpreter_entry_trampoline->instruction_end()) || |
| 197 (pc >= interpreter_bytecode_advance->instruction_start() && |
| 198 pc < interpreter_bytecode_advance->instruction_end()) || |
| 199 (pc >= interpreter_bytecode_dispatch->instruction_start() && |
| 200 pc < interpreter_bytecode_dispatch->instruction_end()); |
| 201 } |
| 202 |
| 203 DISABLE_ASAN Address ReadMemoryAt(Address address) { |
| 204 return Memory::Address_at(address); |
| 205 } |
| 206 |
| 207 } // namespace |
185 | 208 |
186 SafeStackFrameIterator::SafeStackFrameIterator( | 209 SafeStackFrameIterator::SafeStackFrameIterator( |
187 Isolate* isolate, | 210 Isolate* isolate, |
188 Address fp, Address sp, Address js_entry_sp) | 211 Address fp, Address sp, Address js_entry_sp) |
189 : StackFrameIteratorBase(isolate, false), | 212 : StackFrameIteratorBase(isolate, false), |
190 low_bound_(sp), | 213 low_bound_(sp), |
191 high_bound_(js_entry_sp), | 214 high_bound_(js_entry_sp), |
192 top_frame_type_(StackFrame::NONE), | 215 top_frame_type_(StackFrame::NONE), |
193 external_callback_scope_(isolate->external_callback_scope()) { | 216 external_callback_scope_(isolate->external_callback_scope()) { |
194 StackFrame::State state; | 217 StackFrame::State state; |
195 StackFrame::Type type; | 218 StackFrame::Type type; |
196 ThreadLocalTop* top = isolate->thread_local_top(); | 219 ThreadLocalTop* top = isolate->thread_local_top(); |
| 220 bool advance_frame = true; |
197 if (IsValidTop(top)) { | 221 if (IsValidTop(top)) { |
198 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); | 222 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); |
199 top_frame_type_ = type; | 223 top_frame_type_ = type; |
200 } else if (IsValidStackAddress(fp)) { | 224 } else if (IsValidStackAddress(fp)) { |
201 DCHECK(fp != NULL); | 225 DCHECK(fp != NULL); |
202 state.fp = fp; | 226 state.fp = fp; |
203 state.sp = sp; | 227 state.sp = sp; |
204 state.pc_address = StackFrame::ResolveReturnAddressLocation( | 228 state.pc_address = StackFrame::ResolveReturnAddressLocation( |
205 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); | 229 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); |
| 230 |
| 231 // If the top of stack is a return address to the interpreter trampoline, |
| 232 // then we are likely in a bytecode handler with elided frame. In that |
| 233 // case, set the PC properly and make sure we do not drop the frame. |
| 234 if (IsValidStackAddress(sp)) { |
| 235 MSAN_MEMORY_IS_INITIALIZED(sp, kPointerSize); |
| 236 Address tos = ReadMemoryAt(reinterpret_cast<Address>(sp)); |
| 237 if (IsInterpreterFramePc(isolate, tos)) { |
| 238 state.pc_address = reinterpret_cast<Address*>(sp); |
| 239 advance_frame = false; |
| 240 } |
| 241 } |
| 242 |
206 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, | 243 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, |
207 // we check only that kMarkerOffset is within the stack bounds and do | 244 // we check only that kMarkerOffset is within the stack bounds and do |
208 // compile time check that kContextOffset slot is pushed on the stack before | 245 // compile time check that kContextOffset slot is pushed on the stack before |
209 // kMarkerOffset. | 246 // kMarkerOffset. |
210 STATIC_ASSERT(StandardFrameConstants::kFunctionOffset < | 247 STATIC_ASSERT(StandardFrameConstants::kFunctionOffset < |
211 StandardFrameConstants::kContextOffset); | 248 StandardFrameConstants::kContextOffset); |
212 Address frame_marker = fp + StandardFrameConstants::kFunctionOffset; | 249 Address frame_marker = fp + StandardFrameConstants::kFunctionOffset; |
213 if (IsValidStackAddress(frame_marker)) { | 250 if (IsValidStackAddress(frame_marker)) { |
214 type = StackFrame::ComputeType(this, &state); | 251 type = StackFrame::ComputeType(this, &state); |
215 top_frame_type_ = type; | 252 top_frame_type_ = type; |
| 253 // We only keep the top frame if we believe it to be interpreted frame. |
| 254 if (type != StackFrame::INTERPRETED) { |
| 255 advance_frame = true; |
| 256 } |
216 } else { | 257 } else { |
217 // Mark the frame as JAVA_SCRIPT if we cannot determine its type. | 258 // Mark the frame as JAVA_SCRIPT if we cannot determine its type. |
218 // The frame anyways will be skipped. | 259 // The frame anyways will be skipped. |
219 type = StackFrame::JAVA_SCRIPT; | 260 type = StackFrame::JAVA_SCRIPT; |
220 // Top frame is incomplete so we cannot reliably determine its type. | 261 // Top frame is incomplete so we cannot reliably determine its type. |
221 top_frame_type_ = StackFrame::NONE; | 262 top_frame_type_ = StackFrame::NONE; |
222 } | 263 } |
223 } else { | 264 } else { |
224 return; | 265 return; |
225 } | 266 } |
226 frame_ = SingletonFor(type, &state); | 267 frame_ = SingletonFor(type, &state); |
227 if (frame_) Advance(); | 268 if (advance_frame && frame_) Advance(); |
228 } | 269 } |
229 | 270 |
230 | 271 |
231 bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const { | 272 bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const { |
232 Address c_entry_fp = Isolate::c_entry_fp(top); | 273 Address c_entry_fp = Isolate::c_entry_fp(top); |
233 if (!IsValidExitFrame(c_entry_fp)) return false; | 274 if (!IsValidExitFrame(c_entry_fp)) return false; |
234 // There should be at least one JS_ENTRY stack handler. | 275 // There should be at least one JS_ENTRY stack handler. |
235 Address handler = Isolate::handler(top); | 276 Address handler = Isolate::handler(top); |
236 if (handler == NULL) return false; | 277 if (handler == NULL) return false; |
237 // Check that there are no js frames on top of the native frames. | 278 // Check that there are no js frames on top of the native frames. |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 } | 423 } |
383 } | 424 } |
384 | 425 |
385 | 426 |
386 void StackFrame::SetReturnAddressLocationResolver( | 427 void StackFrame::SetReturnAddressLocationResolver( |
387 ReturnAddressLocationResolver resolver) { | 428 ReturnAddressLocationResolver resolver) { |
388 DCHECK(return_address_location_resolver_ == NULL); | 429 DCHECK(return_address_location_resolver_ == NULL); |
389 return_address_location_resolver_ = resolver; | 430 return_address_location_resolver_ = resolver; |
390 } | 431 } |
391 | 432 |
392 static bool IsInterpreterFramePc(Isolate* isolate, Address pc) { | |
393 Code* interpreter_entry_trampoline = | |
394 isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline); | |
395 Code* interpreter_bytecode_advance = | |
396 isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeAdvance); | |
397 Code* interpreter_bytecode_dispatch = | |
398 isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch); | |
399 | |
400 return (pc >= interpreter_entry_trampoline->instruction_start() && | |
401 pc < interpreter_entry_trampoline->instruction_end()) || | |
402 (pc >= interpreter_bytecode_advance->instruction_start() && | |
403 pc < interpreter_bytecode_advance->instruction_end()) || | |
404 (pc >= interpreter_bytecode_dispatch->instruction_start() && | |
405 pc < interpreter_bytecode_dispatch->instruction_end()); | |
406 } | |
407 | |
408 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, | 433 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, |
409 State* state) { | 434 State* state) { |
410 DCHECK(state->fp != NULL); | 435 DCHECK(state->fp != NULL); |
411 | 436 |
412 MSAN_MEMORY_IS_INITIALIZED( | 437 MSAN_MEMORY_IS_INITIALIZED( |
413 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset, | 438 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset, |
414 kPointerSize); | 439 kPointerSize); |
415 Object* marker = Memory::Object_at( | 440 Object* marker = Memory::Object_at( |
416 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset); | 441 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset); |
417 if (!iterator->can_access_heap_objects_) { | 442 if (!iterator->can_access_heap_objects_) { |
(...skipping 1819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2237 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 2262 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
2238 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 2263 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
2239 list.Add(frame, zone); | 2264 list.Add(frame, zone); |
2240 } | 2265 } |
2241 return list.ToVector(); | 2266 return list.ToVector(); |
2242 } | 2267 } |
2243 | 2268 |
2244 | 2269 |
2245 } // namespace internal | 2270 } // namespace internal |
2246 } // namespace v8 | 2271 } // namespace v8 |
OLD | NEW |