| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 private: | 81 private: |
| 82 const Address limit_; | 82 const Address limit_; |
| 83 StackHandler* handler_; | 83 StackHandler* handler_; |
| 84 }; | 84 }; |
| 85 | 85 |
| 86 | 86 |
| 87 // ------------------------------------------------------------------------- | 87 // ------------------------------------------------------------------------- |
| 88 | 88 |
| 89 | 89 |
| 90 #define INITIALIZE_SINGLETON(type, field) field##_(this), | 90 #define INITIALIZE_SINGLETON(type, field) field##_(this), |
| 91 StackFrameIterator::StackFrameIterator(Isolate* isolate) | 91 StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate, |
| 92 bool can_access_heap_objects) |
| 92 : isolate_(isolate), | 93 : isolate_(isolate), |
| 93 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 94 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
| 94 frame_(NULL), handler_(NULL), | 95 frame_(NULL), handler_(NULL), |
| 95 thread_(isolate_->thread_local_top()), | 96 can_access_heap_objects_(can_access_heap_objects) { |
| 96 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { | |
| 97 Reset(); | |
| 98 } | 97 } |
| 99 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) | |
| 100 : isolate_(isolate), | |
| 101 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | |
| 102 frame_(NULL), handler_(NULL), thread_(t), | |
| 103 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { | |
| 104 Reset(); | |
| 105 } | |
| 106 StackFrameIterator::StackFrameIterator(Isolate* isolate, | |
| 107 bool use_top, Address fp, Address sp) | |
| 108 : isolate_(isolate), | |
| 109 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | |
| 110 frame_(NULL), handler_(NULL), | |
| 111 thread_(use_top ? isolate_->thread_local_top() : NULL), | |
| 112 fp_(use_top ? NULL : fp), sp_(sp), | |
| 113 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler : | |
| 114 &StackFrameIterator::AdvanceWithoutHandler) { | |
| 115 if (use_top || fp != NULL) { | |
| 116 Reset(); | |
| 117 } | |
| 118 } | |
| 119 | |
| 120 #undef INITIALIZE_SINGLETON | 98 #undef INITIALIZE_SINGLETON |
| 121 | 99 |
| 122 | 100 |
| 123 void StackFrameIterator::AdvanceWithHandler() { | 101 StackFrameIterator::StackFrameIterator(Isolate* isolate) |
| 102 : StackFrameIteratorBase(isolate, true) { |
| 103 Reset(isolate->thread_local_top()); |
| 104 } |
| 105 |
| 106 |
| 107 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) |
| 108 : StackFrameIteratorBase(isolate, true) { |
| 109 Reset(t); |
| 110 } |
| 111 |
| 112 |
| 113 void StackFrameIterator::Advance() { |
| 124 ASSERT(!done()); | 114 ASSERT(!done()); |
| 125 // Compute the state of the calling frame before restoring | 115 // Compute the state of the calling frame before restoring |
| 126 // callee-saved registers and unwinding handlers. This allows the | 116 // callee-saved registers and unwinding handlers. This allows the |
| 127 // frame code that computes the caller state to access the top | 117 // frame code that computes the caller state to access the top |
| 128 // handler and the value of any callee-saved register if needed. | 118 // handler and the value of any callee-saved register if needed. |
| 129 StackFrame::State state; | 119 StackFrame::State state; |
| 130 StackFrame::Type type = frame_->GetCallerState(&state); | 120 StackFrame::Type type = frame_->GetCallerState(&state); |
| 131 | 121 |
| 132 // Unwind handlers corresponding to the current frame. | 122 // Unwind handlers corresponding to the current frame. |
| 133 StackHandlerIterator it(frame_, handler_); | 123 StackHandlerIterator it(frame_, handler_); |
| 134 while (!it.done()) it.Advance(); | 124 while (!it.done()) it.Advance(); |
| 135 handler_ = it.handler(); | 125 handler_ = it.handler(); |
| 136 | 126 |
| 137 // Advance to the calling frame. | 127 // Advance to the calling frame. |
| 138 frame_ = SingletonFor(type, &state); | 128 frame_ = SingletonFor(type, &state); |
| 139 | 129 |
| 140 // When we're done iterating over the stack frames, the handler | 130 // When we're done iterating over the stack frames, the handler |
| 141 // chain must have been completely unwound. | 131 // chain must have been completely unwound. |
| 142 ASSERT(!done() || handler_ == NULL); | 132 ASSERT(!done() || handler_ == NULL); |
| 143 } | 133 } |
| 144 | 134 |
| 145 | 135 |
| 146 void StackFrameIterator::AdvanceWithoutHandler() { | 136 void StackFrameIterator::Reset(ThreadLocalTop* top) { |
| 147 // A simpler version of Advance which doesn't care about handler. | |
| 148 ASSERT(!done()); | |
| 149 StackFrame::State state; | 137 StackFrame::State state; |
| 150 StackFrame::Type type = frame_->GetCallerState(&state); | 138 StackFrame::Type type = ExitFrame::GetStateForFramePointer( |
| 151 frame_ = SingletonFor(type, &state); | 139 Isolate::c_entry_fp(top), &state); |
| 152 } | 140 handler_ = StackHandler::FromAddress(Isolate::handler(top)); |
| 153 | |
| 154 | |
| 155 void StackFrameIterator::Reset() { | |
| 156 StackFrame::State state; | |
| 157 StackFrame::Type type; | |
| 158 if (thread_ != NULL) { | |
| 159 type = ExitFrame::GetStateForFramePointer( | |
| 160 Isolate::c_entry_fp(thread_), &state); | |
| 161 handler_ = StackHandler::FromAddress( | |
| 162 Isolate::handler(thread_)); | |
| 163 } else { | |
| 164 ASSERT(fp_ != NULL); | |
| 165 state.fp = fp_; | |
| 166 state.sp = sp_; | |
| 167 state.pc_address = ResolveReturnAddressLocation( | |
| 168 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_))); | |
| 169 type = StackFrame::ComputeType(isolate(), &state); | |
| 170 } | |
| 171 if (SingletonFor(type) == NULL) return; | 141 if (SingletonFor(type) == NULL) return; |
| 172 frame_ = SingletonFor(type, &state); | 142 frame_ = SingletonFor(type, &state); |
| 173 } | 143 } |
| 174 | 144 |
| 175 | 145 |
| 176 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type, | 146 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type, |
| 177 StackFrame::State* state) { | 147 StackFrame::State* state) { |
| 178 if (type == StackFrame::NONE) return NULL; | 148 if (type == StackFrame::NONE) return NULL; |
| 179 StackFrame* result = SingletonFor(type); | 149 StackFrame* result = SingletonFor(type); |
| 180 ASSERT(result != NULL); | 150 ASSERT(result != NULL); |
| 181 result->state_ = *state; | 151 result->state_ = *state; |
| 182 return result; | 152 return result; |
| 183 } | 153 } |
| 184 | 154 |
| 185 | 155 |
| 186 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) { | 156 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) { |
| 187 #define FRAME_TYPE_CASE(type, field) \ | 157 #define FRAME_TYPE_CASE(type, field) \ |
| 188 case StackFrame::type: result = &field##_; break; | 158 case StackFrame::type: result = &field##_; break; |
| 189 | 159 |
| 190 StackFrame* result = NULL; | 160 StackFrame* result = NULL; |
| 191 switch (type) { | 161 switch (type) { |
| 192 case StackFrame::NONE: return NULL; | 162 case StackFrame::NONE: return NULL; |
| 193 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) | 163 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) |
| 194 default: break; | 164 default: break; |
| 195 } | 165 } |
| 196 return result; | 166 return result; |
| 197 | 167 |
| 198 #undef FRAME_TYPE_CASE | 168 #undef FRAME_TYPE_CASE |
| 199 } | 169 } |
| 200 | 170 |
| 201 | 171 |
| 202 // ------------------------------------------------------------------------- | 172 // ------------------------------------------------------------------------- |
| 203 | 173 |
| 204 | 174 |
| 175 JavaScriptFrameIterator::JavaScriptFrameIterator( |
| 176 Isolate* isolate, StackFrame::Id id) |
| 177 : iterator_(isolate) { |
| 178 while (!done()) { |
| 179 Advance(); |
| 180 if (frame()->id() == id) return; |
| 181 } |
| 182 } |
| 183 |
| 184 |
| 185 void JavaScriptFrameIterator::Advance() { |
| 186 do { |
| 187 iterator_.Advance(); |
| 188 } while (!iterator_.done() && !iterator_.frame()->is_java_script()); |
| 189 } |
| 190 |
| 191 |
| 192 void JavaScriptFrameIterator::AdvanceToArgumentsFrame() { |
| 193 if (!frame()->has_adapted_arguments()) return; |
| 194 iterator_.Advance(); |
| 195 ASSERT(iterator_.frame()->is_arguments_adaptor()); |
| 196 } |
| 197 |
| 198 |
| 199 // ------------------------------------------------------------------------- |
| 200 |
| 201 |
| 205 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) | 202 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) |
| 206 : JavaScriptFrameIterator(isolate) { | 203 : JavaScriptFrameIterator(isolate) { |
| 207 if (!done() && !IsValidFrame()) Advance(); | 204 if (!done() && !IsValidFrame()) Advance(); |
| 208 } | 205 } |
| 209 | 206 |
| 210 | 207 |
| 211 void StackTraceFrameIterator::Advance() { | 208 void StackTraceFrameIterator::Advance() { |
| 212 while (true) { | 209 while (true) { |
| 213 JavaScriptFrameIterator::Advance(); | 210 JavaScriptFrameIterator::Advance(); |
| 214 if (done()) return; | 211 if (done()) return; |
| 215 if (IsValidFrame()) return; | 212 if (IsValidFrame()) return; |
| 216 } | 213 } |
| 217 } | 214 } |
| 218 | 215 |
| 219 bool StackTraceFrameIterator::IsValidFrame() { | 216 bool StackTraceFrameIterator::IsValidFrame() { |
| 220 if (!frame()->function()->IsJSFunction()) return false; | 217 if (!frame()->function()->IsJSFunction()) return false; |
| 221 Object* script = JSFunction::cast(frame()->function())->shared()->script(); | 218 Object* script = JSFunction::cast(frame()->function())->shared()->script(); |
| 222 // Don't show functions from native scripts to user. | 219 // Don't show functions from native scripts to user. |
| 223 return (script->IsScript() && | 220 return (script->IsScript() && |
| 224 Script::TYPE_NATIVE != Script::cast(script)->type()->value()); | 221 Script::TYPE_NATIVE != Script::cast(script)->type()->value()); |
| 225 } | 222 } |
| 226 | 223 |
| 227 | 224 |
| 228 // ------------------------------------------------------------------------- | 225 // ------------------------------------------------------------------------- |
| 229 | 226 |
| 230 | 227 |
| 231 bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) { | |
| 232 if (!validator_.IsValid(fp)) return false; | |
| 233 Address sp = ExitFrame::ComputeStackPointer(fp); | |
| 234 if (!validator_.IsValid(sp)) return false; | |
| 235 StackFrame::State state; | |
| 236 ExitFrame::FillState(fp, sp, &state); | |
| 237 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) { | |
| 238 return false; | |
| 239 } | |
| 240 return *state.pc_address != NULL; | |
| 241 } | |
| 242 | |
| 243 | |
| 244 SafeStackFrameIterator::ActiveCountMaintainer::ActiveCountMaintainer( | |
| 245 Isolate* isolate) | |
| 246 : isolate_(isolate) { | |
| 247 isolate_->set_safe_stack_iterator_counter( | |
| 248 isolate_->safe_stack_iterator_counter() + 1); | |
| 249 } | |
| 250 | |
| 251 | |
| 252 SafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() { | |
| 253 isolate_->set_safe_stack_iterator_counter( | |
| 254 isolate_->safe_stack_iterator_counter() - 1); | |
| 255 } | |
| 256 | |
| 257 | |
| 258 SafeStackFrameIterator::SafeStackFrameIterator( | 228 SafeStackFrameIterator::SafeStackFrameIterator( |
| 259 Isolate* isolate, | 229 Isolate* isolate, |
| 260 Address fp, Address sp, Address low_bound, Address high_bound) : | 230 Address fp, Address sp, Address low_bound, Address high_bound) : |
| 261 maintainer_(isolate), | 231 StackFrameIteratorBase(isolate, false), |
| 262 stack_validator_(low_bound, high_bound), | 232 low_bound_(low_bound), high_bound_(high_bound) { |
| 263 is_valid_top_(IsValidTop(isolate, low_bound, high_bound)), | 233 StackFrame::State state; |
| 264 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), | 234 StackFrame::Type type; |
| 265 is_working_iterator_(is_valid_top_ || is_valid_fp_), | 235 ThreadLocalTop* top = isolate->thread_local_top(); |
| 266 iteration_done_(!is_working_iterator_), | 236 if (IsValidTop(top)) { |
| 267 iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { | 237 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); |
| 268 } | 238 } else if (IsValidStackAddress(fp)) { |
| 239 ASSERT(fp != NULL); |
| 240 state.fp = fp; |
| 241 state.sp = sp; |
| 242 state.pc_address = ResolveReturnAddressLocation( |
| 243 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); |
| 244 type = StackFrame::ComputeType(this, &state); |
| 245 } else { |
| 246 return; |
| 247 } |
| 248 if (SingletonFor(type) == NULL) return; |
| 249 frame_ = SingletonFor(type, &state); |
| 269 | 250 |
| 270 bool SafeStackFrameIterator::is_active(Isolate* isolate) { | 251 if (!done()) Advance(); |
| 271 return isolate->safe_stack_iterator_counter() > 0; | |
| 272 } | 252 } |
| 273 | 253 |
| 274 | 254 |
| 275 bool SafeStackFrameIterator::IsValidTop(Isolate* isolate, | 255 bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const { |
| 276 Address low_bound, Address high_bound) { | |
| 277 ThreadLocalTop* top = isolate->thread_local_top(); | |
| 278 Address fp = Isolate::c_entry_fp(top); | 256 Address fp = Isolate::c_entry_fp(top); |
| 279 ExitFrameValidator validator(low_bound, high_bound); | 257 if (!IsValidExitFrame(fp)) return false; |
| 280 if (!validator.IsValidFP(fp)) return false; | 258 // There should be at least one JS_ENTRY stack handler. |
| 281 return Isolate::handler(top) != NULL; | 259 return Isolate::handler(top) != NULL; |
| 282 } | 260 } |
| 283 | 261 |
| 284 | 262 |
| 285 void SafeStackFrameIterator::Advance() { | 263 void SafeStackFrameIterator::AdvanceOneFrame() { |
| 286 ASSERT(is_working_iterator_); | |
| 287 ASSERT(!done()); | 264 ASSERT(!done()); |
| 288 StackFrame* last_frame = iterator_.frame(); | 265 StackFrame* last_frame = frame_; |
| 289 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); | 266 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); |
| 290 // Before advancing to the next stack frame, perform pointer validity tests | 267 // Before advancing to the next stack frame, perform pointer validity tests. |
| 291 iteration_done_ = !IsValidFrame(last_frame) || | 268 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) { |
| 292 !CanIterateHandles(last_frame, iterator_.handler()) || | 269 frame_ = NULL; |
| 293 !IsValidCaller(last_frame); | 270 return; |
| 294 if (iteration_done_) return; | 271 } |
| 295 | 272 |
| 296 iterator_.Advance(); | 273 // Advance to the previous frame. |
| 297 if (iterator_.done()) return; | 274 StackFrame::State state; |
| 298 // Check that we have actually moved to the previous frame in the stack | 275 StackFrame::Type type = frame_->GetCallerState(&state); |
| 299 StackFrame* prev_frame = iterator_.frame(); | 276 frame_ = SingletonFor(type, &state); |
| 300 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp; | 277 if (frame_ == NULL) return; |
| 278 |
| 279 // Check that we have actually moved to the previous frame in the stack. |
| 280 if (frame_->sp() < last_sp || frame_->fp() < last_fp) { |
| 281 frame_ = NULL; |
| 282 } |
| 301 } | 283 } |
| 302 | 284 |
| 303 | 285 |
| 304 bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame, | |
| 305 StackHandler* handler) { | |
| 306 // If StackIterator iterates over StackHandles, verify that | |
| 307 // StackHandlerIterator can be instantiated (see StackHandlerIterator | |
| 308 // constructor.) | |
| 309 return !is_valid_top_ || (frame->sp() <= handler->address()); | |
| 310 } | |
| 311 | |
| 312 | |
| 313 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const { | 286 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const { |
| 314 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()); | 287 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()); |
| 315 } | 288 } |
| 316 | 289 |
| 317 | 290 |
| 318 bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) { | 291 bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) { |
| 319 StackFrame::State state; | 292 StackFrame::State state; |
| 320 if (frame->is_entry() || frame->is_entry_construct()) { | 293 if (frame->is_entry() || frame->is_entry_construct()) { |
| 321 // See EntryFrame::GetCallerState. It computes the caller FP address | 294 // See EntryFrame::GetCallerState. It computes the caller FP address |
| 322 // and calls ExitFrame::GetStateForFramePointer on it. We need to be | 295 // and calls ExitFrame::GetStateForFramePointer on it. We need to be |
| 323 // sure that caller FP address is valid. | 296 // sure that caller FP address is valid. |
| 324 Address caller_fp = Memory::Address_at( | 297 Address caller_fp = Memory::Address_at( |
| 325 frame->fp() + EntryFrameConstants::kCallerFPOffset); | 298 frame->fp() + EntryFrameConstants::kCallerFPOffset); |
| 326 ExitFrameValidator validator(stack_validator_); | 299 if (!IsValidExitFrame(caller_fp)) return false; |
| 327 if (!validator.IsValidFP(caller_fp)) return false; | |
| 328 } else if (frame->is_arguments_adaptor()) { | 300 } else if (frame->is_arguments_adaptor()) { |
| 329 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that | 301 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that |
| 330 // the number of arguments is stored on stack as Smi. We need to check | 302 // the number of arguments is stored on stack as Smi. We need to check |
| 331 // that it really an Smi. | 303 // that it really an Smi. |
| 332 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)-> | 304 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)-> |
| 333 GetExpression(0); | 305 GetExpression(0); |
| 334 if (!number_of_args->IsSmi()) { | 306 if (!number_of_args->IsSmi()) { |
| 335 return false; | 307 return false; |
| 336 } | 308 } |
| 337 } | 309 } |
| 338 frame->ComputeCallerState(&state); | 310 frame->ComputeCallerState(&state); |
| 339 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) && | 311 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) && |
| 340 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL; | 312 SingletonFor(frame->GetCallerState(&state)) != NULL; |
| 341 } | 313 } |
| 342 | 314 |
| 343 | 315 |
| 344 void SafeStackFrameIterator::Reset() { | 316 bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const { |
| 345 if (is_working_iterator_) { | 317 if (!IsValidStackAddress(fp)) return false; |
| 346 iterator_.Reset(); | 318 Address sp = ExitFrame::ComputeStackPointer(fp); |
| 347 iteration_done_ = false; | 319 if (!IsValidStackAddress(sp)) return false; |
| 320 StackFrame::State state; |
| 321 ExitFrame::FillState(fp, sp, &state); |
| 322 if (!IsValidStackAddress(reinterpret_cast<Address>(state.pc_address))) { |
| 323 return false; |
| 324 } |
| 325 return *state.pc_address != NULL; |
| 326 } |
| 327 |
| 328 |
| 329 void SafeStackFrameIterator::Advance() { |
| 330 while (true) { |
| 331 AdvanceOneFrame(); |
| 332 if (done()) return; |
| 333 if (frame_->is_java_script()) return; |
| 348 } | 334 } |
| 349 } | 335 } |
| 350 | 336 |
| 351 | 337 |
| 352 // ------------------------------------------------------------------------- | 338 // ------------------------------------------------------------------------- |
| 353 | 339 |
| 354 | 340 |
| 355 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator( | |
| 356 Isolate* isolate, | |
| 357 Address fp, Address sp, Address low_bound, Address high_bound) : | |
| 358 SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) { | |
| 359 if (!done() && !frame()->is_java_script()) Advance(); | |
| 360 } | |
| 361 | |
| 362 | |
| 363 void SafeStackTraceFrameIterator::Advance() { | |
| 364 while (true) { | |
| 365 SafeJavaScriptFrameIterator::Advance(); | |
| 366 if (done()) return; | |
| 367 if (frame()->is_java_script()) return; | |
| 368 } | |
| 369 } | |
| 370 | |
| 371 | |
| 372 Code* StackFrame::GetSafepointData(Isolate* isolate, | 341 Code* StackFrame::GetSafepointData(Isolate* isolate, |
| 373 Address inner_pointer, | 342 Address inner_pointer, |
| 374 SafepointEntry* safepoint_entry, | 343 SafepointEntry* safepoint_entry, |
| 375 unsigned* stack_slots) { | 344 unsigned* stack_slots) { |
| 376 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry = | 345 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry = |
| 377 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer); | 346 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer); |
| 378 if (!entry->safepoint_entry.is_valid()) { | 347 if (!entry->safepoint_entry.is_valid()) { |
| 379 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer); | 348 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer); |
| 380 ASSERT(entry->safepoint_entry.is_valid()); | 349 ASSERT(entry->safepoint_entry.is_valid()); |
| 381 } else { | 350 } else { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 } | 387 } |
| 419 | 388 |
| 420 | 389 |
| 421 void StackFrame::SetReturnAddressLocationResolver( | 390 void StackFrame::SetReturnAddressLocationResolver( |
| 422 ReturnAddressLocationResolver resolver) { | 391 ReturnAddressLocationResolver resolver) { |
| 423 ASSERT(return_address_location_resolver == NULL); | 392 ASSERT(return_address_location_resolver == NULL); |
| 424 return_address_location_resolver = resolver; | 393 return_address_location_resolver = resolver; |
| 425 } | 394 } |
| 426 | 395 |
| 427 | 396 |
| 428 StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) { | 397 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, |
| 398 State* state) { |
| 429 ASSERT(state->fp != NULL); | 399 ASSERT(state->fp != NULL); |
| 430 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { | 400 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { |
| 431 return ARGUMENTS_ADAPTOR; | 401 return ARGUMENTS_ADAPTOR; |
| 432 } | 402 } |
| 433 // The marker and function offsets overlap. If the marker isn't a | 403 // The marker and function offsets overlap. If the marker isn't a |
| 434 // smi then the frame is a JavaScript frame -- and the marker is | 404 // smi then the frame is a JavaScript frame -- and the marker is |
| 435 // really the function. | 405 // really the function. |
| 436 const int offset = StandardFrameConstants::kMarkerOffset; | 406 const int offset = StandardFrameConstants::kMarkerOffset; |
| 437 Object* marker = Memory::Object_at(state->fp + offset); | 407 Object* marker = Memory::Object_at(state->fp + offset); |
| 438 if (!marker->IsSmi()) { | 408 if (!marker->IsSmi()) { |
| 439 // If we're using a "safe" stack iterator, we treat optimized | 409 // If we're using a "safe" stack iterator, we treat optimized |
| 440 // frames as normal JavaScript frames to avoid having to look | 410 // frames as normal JavaScript frames to avoid having to look |
| 441 // into the heap to determine the state. This is safe as long | 411 // into the heap to determine the state. This is safe as long |
| 442 // as nobody tries to GC... | 412 // as nobody tries to GC... |
| 443 if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT; | 413 if (!iterator->can_access_heap_objects_) return JAVA_SCRIPT; |
| 444 Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind(); | 414 Code::Kind kind = GetContainingCode(iterator->isolate(), |
| 415 *(state->pc_address))->kind(); |
| 445 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION); | 416 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION); |
| 446 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT; | 417 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT; |
| 447 } | 418 } |
| 448 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); | 419 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); |
| 449 } | 420 } |
| 450 | 421 |
| 451 | 422 |
| 423 #ifdef DEBUG |
| 424 bool StackFrame::can_access_heap_objects() const { |
| 425 return iterator_->can_access_heap_objects_; |
| 426 } |
| 427 #endif |
| 428 |
| 452 | 429 |
| 453 StackFrame::Type StackFrame::GetCallerState(State* state) const { | 430 StackFrame::Type StackFrame::GetCallerState(State* state) const { |
| 454 ComputeCallerState(state); | 431 ComputeCallerState(state); |
| 455 return ComputeType(isolate(), state); | 432 return ComputeType(iterator_, state); |
| 456 } | 433 } |
| 457 | 434 |
| 458 | 435 |
| 459 Address StackFrame::UnpaddedFP() const { | 436 Address StackFrame::UnpaddedFP() const { |
| 460 #if defined(V8_TARGET_ARCH_IA32) | 437 #if defined(V8_TARGET_ARCH_IA32) |
| 461 if (!is_optimized()) return fp(); | 438 if (!is_optimized()) return fp(); |
| 462 int32_t alignment_state = Memory::int32_at( | 439 int32_t alignment_state = Memory::int32_at( |
| 463 fp() + JavaScriptFrameConstants::kDynamicAlignmentStateOffset); | 440 fp() + JavaScriptFrameConstants::kDynamicAlignmentStateOffset); |
| 464 | 441 |
| 465 return (alignment_state == kAlignmentPaddingPushed) ? | 442 return (alignment_state == kAlignmentPaddingPushed) ? |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 | 515 |
| 539 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { | 516 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { |
| 540 if (fp == 0) return NONE; | 517 if (fp == 0) return NONE; |
| 541 Address sp = ComputeStackPointer(fp); | 518 Address sp = ComputeStackPointer(fp); |
| 542 FillState(fp, sp, state); | 519 FillState(fp, sp, state); |
| 543 ASSERT(*state->pc_address != NULL); | 520 ASSERT(*state->pc_address != NULL); |
| 544 return EXIT; | 521 return EXIT; |
| 545 } | 522 } |
| 546 | 523 |
| 547 | 524 |
| 525 Address ExitFrame::ComputeStackPointer(Address fp) { |
| 526 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset); |
| 527 } |
| 528 |
| 529 |
| 548 void ExitFrame::FillState(Address fp, Address sp, State* state) { | 530 void ExitFrame::FillState(Address fp, Address sp, State* state) { |
| 549 state->sp = sp; | 531 state->sp = sp; |
| 550 state->fp = fp; | 532 state->fp = fp; |
| 551 state->pc_address = ResolveReturnAddressLocation( | 533 state->pc_address = ResolveReturnAddressLocation( |
| 552 reinterpret_cast<Address*>(sp - 1 * kPointerSize)); | 534 reinterpret_cast<Address*>(sp - 1 * kPointerSize)); |
| 553 } | 535 } |
| 554 | 536 |
| 555 | 537 |
| 556 Address StandardFrame::GetExpressionAddress(int n) const { | 538 Address StandardFrame::GetExpressionAddress(int n) const { |
| 557 const int offset = StandardFrameConstants::kExpressionsOffset; | 539 const int offset = StandardFrameConstants::kExpressionsOffset; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | 582 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { |
| 601 if (it.handler()->includes(address)) return true; | 583 if (it.handler()->includes(address)) return true; |
| 602 } | 584 } |
| 603 return false; | 585 return false; |
| 604 } | 586 } |
| 605 | 587 |
| 606 | 588 |
| 607 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { | 589 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { |
| 608 // Make sure that we're not doing "safe" stack frame iteration. We cannot | 590 // Make sure that we're not doing "safe" stack frame iteration. We cannot |
| 609 // possibly find pointers in optimized frames in that state. | 591 // possibly find pointers in optimized frames in that state. |
| 610 ASSERT(!SafeStackFrameIterator::is_active(isolate())); | 592 ASSERT(can_access_heap_objects()); |
| 611 | 593 |
| 612 // Compute the safepoint information. | 594 // Compute the safepoint information. |
| 613 unsigned stack_slots = 0; | 595 unsigned stack_slots = 0; |
| 614 SafepointEntry safepoint_entry; | 596 SafepointEntry safepoint_entry; |
| 615 Code* code = StackFrame::GetSafepointData( | 597 Code* code = StackFrame::GetSafepointData( |
| 616 isolate(), pc(), &safepoint_entry, &stack_slots); | 598 isolate(), pc(), &safepoint_entry, &stack_slots); |
| 617 unsigned slot_space = stack_slots * kPointerSize; | 599 unsigned slot_space = stack_slots * kPointerSize; |
| 618 | 600 |
| 619 // Visit the outgoing parameters. | 601 // Visit the outgoing parameters. |
| 620 Object** parameters_base = &Memory::Object_at(sp()); | 602 Object** parameters_base = &Memory::Object_at(sp()); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 if (has_adapted_arguments()) { | 709 if (has_adapted_arguments()) { |
| 728 return Smi::cast(GetExpression(caller_fp(), 0))->value(); | 710 return Smi::cast(GetExpression(caller_fp(), 0))->value(); |
| 729 } else { | 711 } else { |
| 730 return GetNumberOfIncomingArguments(); | 712 return GetNumberOfIncomingArguments(); |
| 731 } | 713 } |
| 732 } | 714 } |
| 733 | 715 |
| 734 | 716 |
| 735 Code* JavaScriptFrame::unchecked_code() const { | 717 Code* JavaScriptFrame::unchecked_code() const { |
| 736 JSFunction* function = JSFunction::cast(this->function()); | 718 JSFunction* function = JSFunction::cast(this->function()); |
| 737 return function->unchecked_code(); | 719 return function->code(); |
| 738 } | 720 } |
| 739 | 721 |
| 740 | 722 |
| 741 int JavaScriptFrame::GetNumberOfIncomingArguments() const { | 723 int JavaScriptFrame::GetNumberOfIncomingArguments() const { |
| 742 ASSERT(!SafeStackFrameIterator::is_active(isolate()) && | 724 ASSERT(can_access_heap_objects() && |
| 743 isolate()->heap()->gc_state() == Heap::NOT_IN_GC); | 725 isolate()->heap()->gc_state() == Heap::NOT_IN_GC); |
| 744 | 726 |
| 745 JSFunction* function = JSFunction::cast(this->function()); | 727 JSFunction* function = JSFunction::cast(this->function()); |
| 746 return function->shared()->formal_parameter_count(); | 728 return function->shared()->formal_parameter_count(); |
| 747 } | 729 } |
| 748 | 730 |
| 749 | 731 |
| 750 Address JavaScriptFrame::GetCallerStackPointer() const { | 732 Address JavaScriptFrame::GetCallerStackPointer() const { |
| 751 return fp() + StandardFrameConstants::kCallerSPOffset; | 733 return fp() + StandardFrameConstants::kCallerSPOffset; |
| 752 } | 734 } |
| (...skipping 861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1614 ZoneList<StackFrame*> list(10, zone); | 1596 ZoneList<StackFrame*> list(10, zone); |
| 1615 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1597 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
| 1616 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1598 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
| 1617 list.Add(frame, zone); | 1599 list.Add(frame, zone); |
| 1618 } | 1600 } |
| 1619 return list.ToVector(); | 1601 return list.ToVector(); |
| 1620 } | 1602 } |
| 1621 | 1603 |
| 1622 | 1604 |
| 1623 } } // namespace v8::internal | 1605 } } // namespace v8::internal |
| OLD | NEW |