| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/ast.h" | 7 #include "src/ast.h" |
| 8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
| 9 #include "src/frames-inl.h" | 9 #include "src/frames-inl.h" |
| 10 #include "src/full-codegen.h" | 10 #include "src/full-codegen.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 StackFrame::return_address_location_resolver_ = NULL; | 22 StackFrame::return_address_location_resolver_ = NULL; |
| 23 | 23 |
| 24 | 24 |
| 25 // Iterator that supports traversing the stack handlers of a | 25 // Iterator that supports traversing the stack handlers of a |
| 26 // particular frame. Needs to know the top of the handler chain. | 26 // particular frame. Needs to know the top of the handler chain. |
| 27 class StackHandlerIterator BASE_EMBEDDED { | 27 class StackHandlerIterator BASE_EMBEDDED { |
| 28 public: | 28 public: |
| 29 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) | 29 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) |
| 30 : limit_(frame->fp()), handler_(handler) { | 30 : limit_(frame->fp()), handler_(handler) { |
| 31 // Make sure the handler has already been unwound to this frame. | 31 // Make sure the handler has already been unwound to this frame. |
| 32 ASSERT(frame->sp() <= handler->address()); | 32 DCHECK(frame->sp() <= handler->address()); |
| 33 } | 33 } |
| 34 | 34 |
| 35 StackHandler* handler() const { return handler_; } | 35 StackHandler* handler() const { return handler_; } |
| 36 | 36 |
| 37 bool done() { | 37 bool done() { |
| 38 return handler_ == NULL || handler_->address() > limit_; | 38 return handler_ == NULL || handler_->address() > limit_; |
| 39 } | 39 } |
| 40 void Advance() { | 40 void Advance() { |
| 41 ASSERT(!done()); | 41 DCHECK(!done()); |
| 42 handler_ = handler_->next(); | 42 handler_ = handler_->next(); |
| 43 } | 43 } |
| 44 | 44 |
| 45 private: | 45 private: |
| 46 const Address limit_; | 46 const Address limit_; |
| 47 StackHandler* handler_; | 47 StackHandler* handler_; |
| 48 }; | 48 }; |
| 49 | 49 |
| 50 | 50 |
| 51 // ------------------------------------------------------------------------- | 51 // ------------------------------------------------------------------------- |
| (...skipping 16 matching lines...) Expand all Loading... |
| 68 } | 68 } |
| 69 | 69 |
| 70 | 70 |
| 71 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) | 71 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) |
| 72 : StackFrameIteratorBase(isolate, true) { | 72 : StackFrameIteratorBase(isolate, true) { |
| 73 Reset(t); | 73 Reset(t); |
| 74 } | 74 } |
| 75 | 75 |
| 76 | 76 |
| 77 void StackFrameIterator::Advance() { | 77 void StackFrameIterator::Advance() { |
| 78 ASSERT(!done()); | 78 DCHECK(!done()); |
| 79 // Compute the state of the calling frame before restoring | 79 // Compute the state of the calling frame before restoring |
| 80 // callee-saved registers and unwinding handlers. This allows the | 80 // callee-saved registers and unwinding handlers. This allows the |
| 81 // frame code that computes the caller state to access the top | 81 // frame code that computes the caller state to access the top |
| 82 // handler and the value of any callee-saved register if needed. | 82 // handler and the value of any callee-saved register if needed. |
| 83 StackFrame::State state; | 83 StackFrame::State state; |
| 84 StackFrame::Type type = frame_->GetCallerState(&state); | 84 StackFrame::Type type = frame_->GetCallerState(&state); |
| 85 | 85 |
| 86 // Unwind handlers corresponding to the current frame. | 86 // Unwind handlers corresponding to the current frame. |
| 87 StackHandlerIterator it(frame_, handler_); | 87 StackHandlerIterator it(frame_, handler_); |
| 88 while (!it.done()) it.Advance(); | 88 while (!it.done()) it.Advance(); |
| 89 handler_ = it.handler(); | 89 handler_ = it.handler(); |
| 90 | 90 |
| 91 // Advance to the calling frame. | 91 // Advance to the calling frame. |
| 92 frame_ = SingletonFor(type, &state); | 92 frame_ = SingletonFor(type, &state); |
| 93 | 93 |
| 94 // When we're done iterating over the stack frames, the handler | 94 // When we're done iterating over the stack frames, the handler |
| 95 // chain must have been completely unwound. | 95 // chain must have been completely unwound. |
| 96 ASSERT(!done() || handler_ == NULL); | 96 DCHECK(!done() || handler_ == NULL); |
| 97 } | 97 } |
| 98 | 98 |
| 99 | 99 |
| 100 void StackFrameIterator::Reset(ThreadLocalTop* top) { | 100 void StackFrameIterator::Reset(ThreadLocalTop* top) { |
| 101 StackFrame::State state; | 101 StackFrame::State state; |
| 102 StackFrame::Type type = ExitFrame::GetStateForFramePointer( | 102 StackFrame::Type type = ExitFrame::GetStateForFramePointer( |
| 103 Isolate::c_entry_fp(top), &state); | 103 Isolate::c_entry_fp(top), &state); |
| 104 handler_ = StackHandler::FromAddress(Isolate::handler(top)); | 104 handler_ = StackHandler::FromAddress(Isolate::handler(top)); |
| 105 if (SingletonFor(type) == NULL) return; | 105 if (SingletonFor(type) == NULL) return; |
| 106 frame_ = SingletonFor(type, &state); | 106 frame_ = SingletonFor(type, &state); |
| 107 } | 107 } |
| 108 | 108 |
| 109 | 109 |
| 110 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type, | 110 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type, |
| 111 StackFrame::State* state) { | 111 StackFrame::State* state) { |
| 112 if (type == StackFrame::NONE) return NULL; | 112 if (type == StackFrame::NONE) return NULL; |
| 113 StackFrame* result = SingletonFor(type); | 113 StackFrame* result = SingletonFor(type); |
| 114 ASSERT(result != NULL); | 114 DCHECK(result != NULL); |
| 115 result->state_ = *state; | 115 result->state_ = *state; |
| 116 return result; | 116 return result; |
| 117 } | 117 } |
| 118 | 118 |
| 119 | 119 |
| 120 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) { | 120 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) { |
| 121 #define FRAME_TYPE_CASE(type, field) \ | 121 #define FRAME_TYPE_CASE(type, field) \ |
| 122 case StackFrame::type: result = &field##_; break; | 122 case StackFrame::type: result = &field##_; break; |
| 123 | 123 |
| 124 StackFrame* result = NULL; | 124 StackFrame* result = NULL; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 149 void JavaScriptFrameIterator::Advance() { | 149 void JavaScriptFrameIterator::Advance() { |
| 150 do { | 150 do { |
| 151 iterator_.Advance(); | 151 iterator_.Advance(); |
| 152 } while (!iterator_.done() && !iterator_.frame()->is_java_script()); | 152 } while (!iterator_.done() && !iterator_.frame()->is_java_script()); |
| 153 } | 153 } |
| 154 | 154 |
| 155 | 155 |
| 156 void JavaScriptFrameIterator::AdvanceToArgumentsFrame() { | 156 void JavaScriptFrameIterator::AdvanceToArgumentsFrame() { |
| 157 if (!frame()->has_adapted_arguments()) return; | 157 if (!frame()->has_adapted_arguments()) return; |
| 158 iterator_.Advance(); | 158 iterator_.Advance(); |
| 159 ASSERT(iterator_.frame()->is_arguments_adaptor()); | 159 DCHECK(iterator_.frame()->is_arguments_adaptor()); |
| 160 } | 160 } |
| 161 | 161 |
| 162 | 162 |
| 163 // ------------------------------------------------------------------------- | 163 // ------------------------------------------------------------------------- |
| 164 | 164 |
| 165 | 165 |
| 166 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) | 166 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) |
| 167 : JavaScriptFrameIterator(isolate) { | 167 : JavaScriptFrameIterator(isolate) { |
| 168 if (!done() && !IsValidFrame()) Advance(); | 168 if (!done() && !IsValidFrame()) Advance(); |
| 169 } | 169 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 198 high_bound_(js_entry_sp), | 198 high_bound_(js_entry_sp), |
| 199 top_frame_type_(StackFrame::NONE), | 199 top_frame_type_(StackFrame::NONE), |
| 200 external_callback_scope_(isolate->external_callback_scope()) { | 200 external_callback_scope_(isolate->external_callback_scope()) { |
| 201 StackFrame::State state; | 201 StackFrame::State state; |
| 202 StackFrame::Type type; | 202 StackFrame::Type type; |
| 203 ThreadLocalTop* top = isolate->thread_local_top(); | 203 ThreadLocalTop* top = isolate->thread_local_top(); |
| 204 if (IsValidTop(top)) { | 204 if (IsValidTop(top)) { |
| 205 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); | 205 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); |
| 206 top_frame_type_ = type; | 206 top_frame_type_ = type; |
| 207 } else if (IsValidStackAddress(fp)) { | 207 } else if (IsValidStackAddress(fp)) { |
| 208 ASSERT(fp != NULL); | 208 DCHECK(fp != NULL); |
| 209 state.fp = fp; | 209 state.fp = fp; |
| 210 state.sp = sp; | 210 state.sp = sp; |
| 211 state.pc_address = StackFrame::ResolveReturnAddressLocation( | 211 state.pc_address = StackFrame::ResolveReturnAddressLocation( |
| 212 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); | 212 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); |
| 213 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, | 213 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, |
| 214 // we check only that kMarkerOffset is within the stack bounds and do | 214 // we check only that kMarkerOffset is within the stack bounds and do |
| 215 // compile time check that kContextOffset slot is pushed on the stack before | 215 // compile time check that kContextOffset slot is pushed on the stack before |
| 216 // kMarkerOffset. | 216 // kMarkerOffset. |
| 217 STATIC_ASSERT(StandardFrameConstants::kMarkerOffset < | 217 STATIC_ASSERT(StandardFrameConstants::kMarkerOffset < |
| 218 StandardFrameConstants::kContextOffset); | 218 StandardFrameConstants::kContextOffset); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 if (!IsValidExitFrame(c_entry_fp)) return false; | 251 if (!IsValidExitFrame(c_entry_fp)) return false; |
| 252 // There should be at least one JS_ENTRY stack handler. | 252 // There should be at least one JS_ENTRY stack handler. |
| 253 Address handler = Isolate::handler(top); | 253 Address handler = Isolate::handler(top); |
| 254 if (handler == NULL) return false; | 254 if (handler == NULL) return false; |
| 255 // Check that there are no js frames on top of the native frames. | 255 // Check that there are no js frames on top of the native frames. |
| 256 return c_entry_fp < handler; | 256 return c_entry_fp < handler; |
| 257 } | 257 } |
| 258 | 258 |
| 259 | 259 |
| 260 void SafeStackFrameIterator::AdvanceOneFrame() { | 260 void SafeStackFrameIterator::AdvanceOneFrame() { |
| 261 ASSERT(!done()); | 261 DCHECK(!done()); |
| 262 StackFrame* last_frame = frame_; | 262 StackFrame* last_frame = frame_; |
| 263 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); | 263 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); |
| 264 // Before advancing to the next stack frame, perform pointer validity tests. | 264 // Before advancing to the next stack frame, perform pointer validity tests. |
| 265 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) { | 265 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) { |
| 266 frame_ = NULL; | 266 frame_ = NULL; |
| 267 return; | 267 return; |
| 268 } | 268 } |
| 269 | 269 |
| 270 // Advance to the previous frame. | 270 // Advance to the previous frame. |
| 271 StackFrame::State state; | 271 StackFrame::State state; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 // frame beneath it. There may be other EXIT frames on top of the | 334 // frame beneath it. There may be other EXIT frames on top of the |
| 335 // ExternalCallbackScope, just skip them as we cannot collect any useful | 335 // ExternalCallbackScope, just skip them as we cannot collect any useful |
| 336 // information about them. | 336 // information about them. |
| 337 if (external_callback_scope_->scope_address() < frame_->fp()) { | 337 if (external_callback_scope_->scope_address() < frame_->fp()) { |
| 338 Address* callback_address = | 338 Address* callback_address = |
| 339 external_callback_scope_->callback_address(); | 339 external_callback_scope_->callback_address(); |
| 340 if (*callback_address != NULL) { | 340 if (*callback_address != NULL) { |
| 341 frame_->state_.pc_address = callback_address; | 341 frame_->state_.pc_address = callback_address; |
| 342 } | 342 } |
| 343 external_callback_scope_ = external_callback_scope_->previous(); | 343 external_callback_scope_ = external_callback_scope_->previous(); |
| 344 ASSERT(external_callback_scope_ == NULL || | 344 DCHECK(external_callback_scope_ == NULL || |
| 345 external_callback_scope_->scope_address() > frame_->fp()); | 345 external_callback_scope_->scope_address() > frame_->fp()); |
| 346 return; | 346 return; |
| 347 } | 347 } |
| 348 } | 348 } |
| 349 } | 349 } |
| 350 } | 350 } |
| 351 | 351 |
| 352 | 352 |
| 353 // ------------------------------------------------------------------------- | 353 // ------------------------------------------------------------------------- |
| 354 | 354 |
| 355 | 355 |
| 356 Code* StackFrame::GetSafepointData(Isolate* isolate, | 356 Code* StackFrame::GetSafepointData(Isolate* isolate, |
| 357 Address inner_pointer, | 357 Address inner_pointer, |
| 358 SafepointEntry* safepoint_entry, | 358 SafepointEntry* safepoint_entry, |
| 359 unsigned* stack_slots) { | 359 unsigned* stack_slots) { |
| 360 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry = | 360 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry = |
| 361 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer); | 361 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer); |
| 362 if (!entry->safepoint_entry.is_valid()) { | 362 if (!entry->safepoint_entry.is_valid()) { |
| 363 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer); | 363 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer); |
| 364 ASSERT(entry->safepoint_entry.is_valid()); | 364 DCHECK(entry->safepoint_entry.is_valid()); |
| 365 } else { | 365 } else { |
| 366 ASSERT(entry->safepoint_entry.Equals( | 366 DCHECK(entry->safepoint_entry.Equals( |
| 367 entry->code->GetSafepointEntry(inner_pointer))); | 367 entry->code->GetSafepointEntry(inner_pointer))); |
| 368 } | 368 } |
| 369 | 369 |
| 370 // Fill in the results and return the code. | 370 // Fill in the results and return the code. |
| 371 Code* code = entry->code; | 371 Code* code = entry->code; |
| 372 *safepoint_entry = entry->safepoint_entry; | 372 *safepoint_entry = entry->safepoint_entry; |
| 373 *stack_slots = code->stack_slots(); | 373 *stack_slots = code->stack_slots(); |
| 374 return code; | 374 return code; |
| 375 } | 375 } |
| 376 | 376 |
| 377 | 377 |
| 378 bool StackFrame::HasHandler() const { | 378 bool StackFrame::HasHandler() const { |
| 379 StackHandlerIterator it(this, top_handler()); | 379 StackHandlerIterator it(this, top_handler()); |
| 380 return !it.done(); | 380 return !it.done(); |
| 381 } | 381 } |
| 382 | 382 |
| 383 | 383 |
| 384 #ifdef DEBUG | 384 #ifdef DEBUG |
| 385 static bool GcSafeCodeContains(HeapObject* object, Address addr); | 385 static bool GcSafeCodeContains(HeapObject* object, Address addr); |
| 386 #endif | 386 #endif |
| 387 | 387 |
| 388 | 388 |
| 389 void StackFrame::IteratePc(ObjectVisitor* v, | 389 void StackFrame::IteratePc(ObjectVisitor* v, |
| 390 Address* pc_address, | 390 Address* pc_address, |
| 391 Code* holder) { | 391 Code* holder) { |
| 392 Address pc = *pc_address; | 392 Address pc = *pc_address; |
| 393 ASSERT(GcSafeCodeContains(holder, pc)); | 393 DCHECK(GcSafeCodeContains(holder, pc)); |
| 394 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start()); | 394 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start()); |
| 395 Object* code = holder; | 395 Object* code = holder; |
| 396 v->VisitPointer(&code); | 396 v->VisitPointer(&code); |
| 397 if (code != holder) { | 397 if (code != holder) { |
| 398 holder = reinterpret_cast<Code*>(code); | 398 holder = reinterpret_cast<Code*>(code); |
| 399 pc = holder->instruction_start() + pc_offset; | 399 pc = holder->instruction_start() + pc_offset; |
| 400 *pc_address = pc; | 400 *pc_address = pc; |
| 401 } | 401 } |
| 402 } | 402 } |
| 403 | 403 |
| 404 | 404 |
| 405 void StackFrame::SetReturnAddressLocationResolver( | 405 void StackFrame::SetReturnAddressLocationResolver( |
| 406 ReturnAddressLocationResolver resolver) { | 406 ReturnAddressLocationResolver resolver) { |
| 407 ASSERT(return_address_location_resolver_ == NULL); | 407 DCHECK(return_address_location_resolver_ == NULL); |
| 408 return_address_location_resolver_ = resolver; | 408 return_address_location_resolver_ = resolver; |
| 409 } | 409 } |
| 410 | 410 |
| 411 | 411 |
| 412 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, | 412 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, |
| 413 State* state) { | 413 State* state) { |
| 414 ASSERT(state->fp != NULL); | 414 DCHECK(state->fp != NULL); |
| 415 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { | 415 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { |
| 416 return ARGUMENTS_ADAPTOR; | 416 return ARGUMENTS_ADAPTOR; |
| 417 } | 417 } |
| 418 // The marker and function offsets overlap. If the marker isn't a | 418 // The marker and function offsets overlap. If the marker isn't a |
| 419 // smi then the frame is a JavaScript frame -- and the marker is | 419 // smi then the frame is a JavaScript frame -- and the marker is |
| 420 // really the function. | 420 // really the function. |
| 421 const int offset = StandardFrameConstants::kMarkerOffset; | 421 const int offset = StandardFrameConstants::kMarkerOffset; |
| 422 Object* marker = Memory::Object_at(state->fp + offset); | 422 Object* marker = Memory::Object_at(state->fp + offset); |
| 423 if (!marker->IsSmi()) { | 423 if (!marker->IsSmi()) { |
| 424 // If we're using a "safe" stack iterator, we treat optimized | 424 // If we're using a "safe" stack iterator, we treat optimized |
| 425 // frames as normal JavaScript frames to avoid having to look | 425 // frames as normal JavaScript frames to avoid having to look |
| 426 // into the heap to determine the state. This is safe as long | 426 // into the heap to determine the state. This is safe as long |
| 427 // as nobody tries to GC... | 427 // as nobody tries to GC... |
| 428 if (!iterator->can_access_heap_objects_) return JAVA_SCRIPT; | 428 if (!iterator->can_access_heap_objects_) return JAVA_SCRIPT; |
| 429 Code::Kind kind = GetContainingCode(iterator->isolate(), | 429 Code::Kind kind = GetContainingCode(iterator->isolate(), |
| 430 *(state->pc_address))->kind(); | 430 *(state->pc_address))->kind(); |
| 431 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION); | 431 DCHECK(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION); |
| 432 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT; | 432 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT; |
| 433 } | 433 } |
| 434 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); | 434 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); |
| 435 } | 435 } |
| 436 | 436 |
| 437 | 437 |
| 438 #ifdef DEBUG | 438 #ifdef DEBUG |
| 439 bool StackFrame::can_access_heap_objects() const { | 439 bool StackFrame::can_access_heap_objects() const { |
| 440 return iterator_->can_access_heap_objects_; | 440 return iterator_->can_access_heap_objects_; |
| 441 } | 441 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 | 532 |
| 533 Address ExitFrame::GetCallerStackPointer() const { | 533 Address ExitFrame::GetCallerStackPointer() const { |
| 534 return fp() + ExitFrameConstants::kCallerSPDisplacement; | 534 return fp() + ExitFrameConstants::kCallerSPDisplacement; |
| 535 } | 535 } |
| 536 | 536 |
| 537 | 537 |
| 538 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { | 538 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { |
| 539 if (fp == 0) return NONE; | 539 if (fp == 0) return NONE; |
| 540 Address sp = ComputeStackPointer(fp); | 540 Address sp = ComputeStackPointer(fp); |
| 541 FillState(fp, sp, state); | 541 FillState(fp, sp, state); |
| 542 ASSERT(*state->pc_address != NULL); | 542 DCHECK(*state->pc_address != NULL); |
| 543 return EXIT; | 543 return EXIT; |
| 544 } | 544 } |
| 545 | 545 |
| 546 | 546 |
| 547 Address ExitFrame::ComputeStackPointer(Address fp) { | 547 Address ExitFrame::ComputeStackPointer(Address fp) { |
| 548 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset); | 548 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset); |
| 549 } | 549 } |
| 550 | 550 |
| 551 | 551 |
| 552 void ExitFrame::FillState(Address fp, Address sp, State* state) { | 552 void ExitFrame::FillState(Address fp, Address sp, State* state) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 574 const int offset = StandardFrameConstants::kExpressionsOffset; | 574 const int offset = StandardFrameConstants::kExpressionsOffset; |
| 575 return fp + offset - n * kPointerSize; | 575 return fp + offset - n * kPointerSize; |
| 576 } | 576 } |
| 577 | 577 |
| 578 | 578 |
| 579 int StandardFrame::ComputeExpressionsCount() const { | 579 int StandardFrame::ComputeExpressionsCount() const { |
| 580 const int offset = | 580 const int offset = |
| 581 StandardFrameConstants::kExpressionsOffset + kPointerSize; | 581 StandardFrameConstants::kExpressionsOffset + kPointerSize; |
| 582 Address base = fp() + offset; | 582 Address base = fp() + offset; |
| 583 Address limit = sp(); | 583 Address limit = sp(); |
| 584 ASSERT(base >= limit); // stack grows downwards | 584 DCHECK(base >= limit); // stack grows downwards |
| 585 // Include register-allocated locals in number of expressions. | 585 // Include register-allocated locals in number of expressions. |
| 586 return static_cast<int>((base - limit) / kPointerSize); | 586 return static_cast<int>((base - limit) / kPointerSize); |
| 587 } | 587 } |
| 588 | 588 |
| 589 | 589 |
| 590 void StandardFrame::ComputeCallerState(State* state) const { | 590 void StandardFrame::ComputeCallerState(State* state) const { |
| 591 state->sp = caller_sp(); | 591 state->sp = caller_sp(); |
| 592 state->fp = caller_fp(); | 592 state->fp = caller_fp(); |
| 593 state->pc_address = ResolveReturnAddressLocation( | 593 state->pc_address = ResolveReturnAddressLocation( |
| 594 reinterpret_cast<Address*>(ComputePCAddress(fp()))); | 594 reinterpret_cast<Address*>(ComputePCAddress(fp()))); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 608 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | 608 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { |
| 609 if (it.handler()->includes(address)) return true; | 609 if (it.handler()->includes(address)) return true; |
| 610 } | 610 } |
| 611 return false; | 611 return false; |
| 612 } | 612 } |
| 613 | 613 |
| 614 | 614 |
| 615 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { | 615 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { |
| 616 // Make sure that we're not doing "safe" stack frame iteration. We cannot | 616 // Make sure that we're not doing "safe" stack frame iteration. We cannot |
| 617 // possibly find pointers in optimized frames in that state. | 617 // possibly find pointers in optimized frames in that state. |
| 618 ASSERT(can_access_heap_objects()); | 618 DCHECK(can_access_heap_objects()); |
| 619 | 619 |
| 620 // Compute the safepoint information. | 620 // Compute the safepoint information. |
| 621 unsigned stack_slots = 0; | 621 unsigned stack_slots = 0; |
| 622 SafepointEntry safepoint_entry; | 622 SafepointEntry safepoint_entry; |
| 623 Code* code = StackFrame::GetSafepointData( | 623 Code* code = StackFrame::GetSafepointData( |
| 624 isolate(), pc(), &safepoint_entry, &stack_slots); | 624 isolate(), pc(), &safepoint_entry, &stack_slots); |
| 625 unsigned slot_space = stack_slots * kPointerSize; | 625 unsigned slot_space = stack_slots * kPointerSize; |
| 626 | 626 |
| 627 // Visit the outgoing parameters. | 627 // Visit the outgoing parameters. |
| 628 Object** parameters_base = &Memory::Object_at(sp()); | 628 Object** parameters_base = &Memory::Object_at(sp()); |
| 629 Object** parameters_limit = &Memory::Object_at( | 629 Object** parameters_limit = &Memory::Object_at( |
| 630 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space); | 630 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space); |
| 631 | 631 |
| 632 // Visit the parameters that may be on top of the saved registers. | 632 // Visit the parameters that may be on top of the saved registers. |
| 633 if (safepoint_entry.argument_count() > 0) { | 633 if (safepoint_entry.argument_count() > 0) { |
| 634 v->VisitPointers(parameters_base, | 634 v->VisitPointers(parameters_base, |
| 635 parameters_base + safepoint_entry.argument_count()); | 635 parameters_base + safepoint_entry.argument_count()); |
| 636 parameters_base += safepoint_entry.argument_count(); | 636 parameters_base += safepoint_entry.argument_count(); |
| 637 } | 637 } |
| 638 | 638 |
| 639 // Skip saved double registers. | 639 // Skip saved double registers. |
| 640 if (safepoint_entry.has_doubles()) { | 640 if (safepoint_entry.has_doubles()) { |
| 641 // Number of doubles not known at snapshot time. | 641 // Number of doubles not known at snapshot time. |
| 642 ASSERT(!isolate()->serializer_enabled()); | 642 DCHECK(!isolate()->serializer_enabled()); |
| 643 parameters_base += DoubleRegister::NumAllocatableRegisters() * | 643 parameters_base += DoubleRegister::NumAllocatableRegisters() * |
| 644 kDoubleSize / kPointerSize; | 644 kDoubleSize / kPointerSize; |
| 645 } | 645 } |
| 646 | 646 |
| 647 // Visit the registers that contain pointers if any. | 647 // Visit the registers that contain pointers if any. |
| 648 if (safepoint_entry.HasRegisters()) { | 648 if (safepoint_entry.HasRegisters()) { |
| 649 for (int i = kNumSafepointRegisters - 1; i >=0; i--) { | 649 for (int i = kNumSafepointRegisters - 1; i >=0; i--) { |
| 650 if (safepoint_entry.HasRegisterAt(i)) { | 650 if (safepoint_entry.HasRegisterAt(i)) { |
| 651 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i); | 651 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i); |
| 652 v->VisitPointer(parameters_base + reg_stack_index); | 652 v->VisitPointer(parameters_base + reg_stack_index); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 | 701 |
| 702 int StubFrame::GetNumberOfIncomingArguments() const { | 702 int StubFrame::GetNumberOfIncomingArguments() const { |
| 703 return 0; | 703 return 0; |
| 704 } | 704 } |
| 705 | 705 |
| 706 | 706 |
| 707 void OptimizedFrame::Iterate(ObjectVisitor* v) const { | 707 void OptimizedFrame::Iterate(ObjectVisitor* v) const { |
| 708 #ifdef DEBUG | 708 #ifdef DEBUG |
| 709 // Make sure that optimized frames do not contain any stack handlers. | 709 // Make sure that optimized frames do not contain any stack handlers. |
| 710 StackHandlerIterator it(this, top_handler()); | 710 StackHandlerIterator it(this, top_handler()); |
| 711 ASSERT(it.done()); | 711 DCHECK(it.done()); |
| 712 #endif | 712 #endif |
| 713 | 713 |
| 714 IterateCompiledFrame(v); | 714 IterateCompiledFrame(v); |
| 715 } | 715 } |
| 716 | 716 |
| 717 | 717 |
| 718 void JavaScriptFrame::SetParameterValue(int index, Object* value) const { | 718 void JavaScriptFrame::SetParameterValue(int index, Object* value) const { |
| 719 Memory::Object_at(GetParameterSlot(index)) = value; | 719 Memory::Object_at(GetParameterSlot(index)) = value; |
| 720 } | 720 } |
| 721 | 721 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 739 } | 739 } |
| 740 } | 740 } |
| 741 | 741 |
| 742 | 742 |
| 743 Code* JavaScriptFrame::unchecked_code() const { | 743 Code* JavaScriptFrame::unchecked_code() const { |
| 744 return function()->code(); | 744 return function()->code(); |
| 745 } | 745 } |
| 746 | 746 |
| 747 | 747 |
| 748 int JavaScriptFrame::GetNumberOfIncomingArguments() const { | 748 int JavaScriptFrame::GetNumberOfIncomingArguments() const { |
| 749 ASSERT(can_access_heap_objects() && | 749 DCHECK(can_access_heap_objects() && |
| 750 isolate()->heap()->gc_state() == Heap::NOT_IN_GC); | 750 isolate()->heap()->gc_state() == Heap::NOT_IN_GC); |
| 751 | 751 |
| 752 return function()->shared()->formal_parameter_count(); | 752 return function()->shared()->formal_parameter_count(); |
| 753 } | 753 } |
| 754 | 754 |
| 755 | 755 |
| 756 Address JavaScriptFrame::GetCallerStackPointer() const { | 756 Address JavaScriptFrame::GetCallerStackPointer() const { |
| 757 return fp() + StandardFrameConstants::kCallerSPOffset; | 757 return fp() + StandardFrameConstants::kCallerSPOffset; |
| 758 } | 758 } |
| 759 | 759 |
| 760 | 760 |
| 761 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) { | 761 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) { |
| 762 ASSERT(functions->length() == 0); | 762 DCHECK(functions->length() == 0); |
| 763 functions->Add(function()); | 763 functions->Add(function()); |
| 764 } | 764 } |
| 765 | 765 |
| 766 | 766 |
| 767 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { | 767 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { |
| 768 ASSERT(functions->length() == 0); | 768 DCHECK(functions->length() == 0); |
| 769 Code* code_pointer = LookupCode(); | 769 Code* code_pointer = LookupCode(); |
| 770 int offset = static_cast<int>(pc() - code_pointer->address()); | 770 int offset = static_cast<int>(pc() - code_pointer->address()); |
| 771 FrameSummary summary(receiver(), | 771 FrameSummary summary(receiver(), |
| 772 function(), | 772 function(), |
| 773 code_pointer, | 773 code_pointer, |
| 774 offset, | 774 offset, |
| 775 IsConstructor()); | 775 IsConstructor()); |
| 776 functions->Add(summary); | 776 functions->Add(summary); |
| 777 } | 777 } |
| 778 | 778 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 break; | 834 break; |
| 835 } | 835 } |
| 836 it.Advance(); | 836 it.Advance(); |
| 837 } | 837 } |
| 838 } | 838 } |
| 839 | 839 |
| 840 | 840 |
| 841 void JavaScriptFrame::SaveOperandStack(FixedArray* store, | 841 void JavaScriptFrame::SaveOperandStack(FixedArray* store, |
| 842 int* stack_handler_index) const { | 842 int* stack_handler_index) const { |
| 843 int operands_count = store->length(); | 843 int operands_count = store->length(); |
| 844 ASSERT_LE(operands_count, ComputeOperandsCount()); | 844 DCHECK_LE(operands_count, ComputeOperandsCount()); |
| 845 | 845 |
| 846 // Visit the stack in LIFO order, saving operands and stack handlers into the | 846 // Visit the stack in LIFO order, saving operands and stack handlers into the |
| 847 // array. The saved stack handlers store a link to the next stack handler, | 847 // array. The saved stack handlers store a link to the next stack handler, |
| 848 // which will allow RestoreOperandStack to rewind the handlers. | 848 // which will allow RestoreOperandStack to rewind the handlers. |
| 849 StackHandlerIterator it(this, top_handler()); | 849 StackHandlerIterator it(this, top_handler()); |
| 850 int i = operands_count - 1; | 850 int i = operands_count - 1; |
| 851 *stack_handler_index = -1; | 851 *stack_handler_index = -1; |
| 852 for (; !it.done(); it.Advance()) { | 852 for (; !it.done(); it.Advance()) { |
| 853 StackHandler* handler = it.handler(); | 853 StackHandler* handler = it.handler(); |
| 854 // Save operands pushed after the handler was pushed. | 854 // Save operands pushed after the handler was pushed. |
| 855 for (; GetOperandSlot(i) < handler->address(); i--) { | 855 for (; GetOperandSlot(i) < handler->address(); i--) { |
| 856 store->set(i, GetOperand(i)); | 856 store->set(i, GetOperand(i)); |
| 857 } | 857 } |
| 858 ASSERT_GE(i + 1, StackHandlerConstants::kSlotCount); | 858 DCHECK_GE(i + 1, StackHandlerConstants::kSlotCount); |
| 859 ASSERT_EQ(handler->address(), GetOperandSlot(i)); | 859 DCHECK_EQ(handler->address(), GetOperandSlot(i)); |
| 860 int next_stack_handler_index = i + 1 - StackHandlerConstants::kSlotCount; | 860 int next_stack_handler_index = i + 1 - StackHandlerConstants::kSlotCount; |
| 861 handler->Unwind(isolate(), store, next_stack_handler_index, | 861 handler->Unwind(isolate(), store, next_stack_handler_index, |
| 862 *stack_handler_index); | 862 *stack_handler_index); |
| 863 *stack_handler_index = next_stack_handler_index; | 863 *stack_handler_index = next_stack_handler_index; |
| 864 i -= StackHandlerConstants::kSlotCount; | 864 i -= StackHandlerConstants::kSlotCount; |
| 865 } | 865 } |
| 866 | 866 |
| 867 // Save any remaining operands. | 867 // Save any remaining operands. |
| 868 for (; i >= 0; i--) { | 868 for (; i >= 0; i--) { |
| 869 store->set(i, GetOperand(i)); | 869 store->set(i, GetOperand(i)); |
| 870 } | 870 } |
| 871 } | 871 } |
| 872 | 872 |
| 873 | 873 |
| 874 void JavaScriptFrame::RestoreOperandStack(FixedArray* store, | 874 void JavaScriptFrame::RestoreOperandStack(FixedArray* store, |
| 875 int stack_handler_index) { | 875 int stack_handler_index) { |
| 876 int operands_count = store->length(); | 876 int operands_count = store->length(); |
| 877 ASSERT_LE(operands_count, ComputeOperandsCount()); | 877 DCHECK_LE(operands_count, ComputeOperandsCount()); |
| 878 int i = 0; | 878 int i = 0; |
| 879 while (i <= stack_handler_index) { | 879 while (i <= stack_handler_index) { |
| 880 if (i < stack_handler_index) { | 880 if (i < stack_handler_index) { |
| 881 // An operand. | 881 // An operand. |
| 882 ASSERT_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); | 882 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); |
| 883 Memory::Object_at(GetOperandSlot(i)) = store->get(i); | 883 Memory::Object_at(GetOperandSlot(i)) = store->get(i); |
| 884 i++; | 884 i++; |
| 885 } else { | 885 } else { |
| 886 // A stack handler. | 886 // A stack handler. |
| 887 ASSERT_EQ(i, stack_handler_index); | 887 DCHECK_EQ(i, stack_handler_index); |
| 888 // The FixedArray store grows up. The stack grows down. So the operand | 888 // The FixedArray store grows up. The stack grows down. So the operand |
| 889 // slot for i actually points to the bottom of the top word in the | 889 // slot for i actually points to the bottom of the top word in the |
| 890 // handler. The base of the StackHandler* is the address of the bottom | 890 // handler. The base of the StackHandler* is the address of the bottom |
| 891 // word, which will be the last slot that is in the handler. | 891 // word, which will be the last slot that is in the handler. |
| 892 int handler_slot_index = i + StackHandlerConstants::kSlotCount - 1; | 892 int handler_slot_index = i + StackHandlerConstants::kSlotCount - 1; |
| 893 StackHandler *handler = | 893 StackHandler *handler = |
| 894 StackHandler::FromAddress(GetOperandSlot(handler_slot_index)); | 894 StackHandler::FromAddress(GetOperandSlot(handler_slot_index)); |
| 895 stack_handler_index = handler->Rewind(isolate(), store, i, fp()); | 895 stack_handler_index = handler->Rewind(isolate(), store, i, fp()); |
| 896 i += StackHandlerConstants::kSlotCount; | 896 i += StackHandlerConstants::kSlotCount; |
| 897 } | 897 } |
| 898 } | 898 } |
| 899 | 899 |
| 900 for (; i < operands_count; i++) { | 900 for (; i < operands_count; i++) { |
| 901 ASSERT_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); | 901 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); |
| 902 Memory::Object_at(GetOperandSlot(i)) = store->get(i); | 902 Memory::Object_at(GetOperandSlot(i)) = store->get(i); |
| 903 } | 903 } |
| 904 } | 904 } |
| 905 | 905 |
| 906 | 906 |
| 907 void FrameSummary::Print() { | 907 void FrameSummary::Print() { |
| 908 PrintF("receiver: "); | 908 PrintF("receiver: "); |
| 909 receiver_->ShortPrint(); | 909 receiver_->ShortPrint(); |
| 910 PrintF("\nfunction: "); | 910 PrintF("\nfunction: "); |
| 911 function_->shared()->DebugName()->ShortPrint(); | 911 function_->shared()->DebugName()->ShortPrint(); |
| 912 PrintF("\ncode: "); | 912 PrintF("\ncode: "); |
| 913 code_->ShortPrint(); | 913 code_->ShortPrint(); |
| 914 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT"); | 914 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT"); |
| 915 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT"); | 915 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT"); |
| 916 PrintF("\npc: %d\n", offset_); | 916 PrintF("\npc: %d\n", offset_); |
| 917 } | 917 } |
| 918 | 918 |
| 919 | 919 |
| 920 JSFunction* OptimizedFrame::LiteralAt(FixedArray* literal_array, | 920 JSFunction* OptimizedFrame::LiteralAt(FixedArray* literal_array, |
| 921 int literal_id) { | 921 int literal_id) { |
| 922 if (literal_id == Translation::kSelfLiteralId) { | 922 if (literal_id == Translation::kSelfLiteralId) { |
| 923 return function(); | 923 return function(); |
| 924 } | 924 } |
| 925 | 925 |
| 926 return JSFunction::cast(literal_array->get(literal_id)); | 926 return JSFunction::cast(literal_array->get(literal_id)); |
| 927 } | 927 } |
| 928 | 928 |
| 929 | 929 |
| 930 void OptimizedFrame::Summarize(List<FrameSummary>* frames) { | 930 void OptimizedFrame::Summarize(List<FrameSummary>* frames) { |
| 931 ASSERT(frames->length() == 0); | 931 DCHECK(frames->length() == 0); |
| 932 ASSERT(is_optimized()); | 932 DCHECK(is_optimized()); |
| 933 | 933 |
| 934 // Delegate to JS frame in absence of inlining. | 934 // Delegate to JS frame in absence of inlining. |
| 935 // TODO(turbofan): Revisit once we support inlining. | 935 // TODO(turbofan): Revisit once we support inlining. |
| 936 if (LookupCode()->is_turbofanned()) { | 936 if (LookupCode()->is_turbofanned()) { |
| 937 return JavaScriptFrame::Summarize(frames); | 937 return JavaScriptFrame::Summarize(frames); |
| 938 } | 938 } |
| 939 | 939 |
| 940 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 940 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
| 941 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); | 941 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); |
| 942 FixedArray* literal_array = data->LiteralArray(); | 942 FixedArray* literal_array = data->LiteralArray(); |
| 943 | 943 |
| 944 // BUG(3243555): Since we don't have a lazy-deopt registered at | 944 // BUG(3243555): Since we don't have a lazy-deopt registered at |
| 945 // throw-statements, we can't use the translation at the call-site of | 945 // throw-statements, we can't use the translation at the call-site of |
| 946 // throw. An entry with no deoptimization index indicates a call-site | 946 // throw. An entry with no deoptimization index indicates a call-site |
| 947 // without a lazy-deopt. As a consequence we are not allowed to inline | 947 // without a lazy-deopt. As a consequence we are not allowed to inline |
| 948 // functions containing throw. | 948 // functions containing throw. |
| 949 ASSERT(deopt_index != Safepoint::kNoDeoptimizationIndex); | 949 DCHECK(deopt_index != Safepoint::kNoDeoptimizationIndex); |
| 950 | 950 |
| 951 TranslationIterator it(data->TranslationByteArray(), | 951 TranslationIterator it(data->TranslationByteArray(), |
| 952 data->TranslationIndex(deopt_index)->value()); | 952 data->TranslationIndex(deopt_index)->value()); |
| 953 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 953 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
| 954 ASSERT(opcode == Translation::BEGIN); | 954 DCHECK(opcode == Translation::BEGIN); |
| 955 it.Next(); // Drop frame count. | 955 it.Next(); // Drop frame count. |
| 956 int jsframe_count = it.Next(); | 956 int jsframe_count = it.Next(); |
| 957 | 957 |
| 958 // We create the summary in reverse order because the frames | 958 // We create the summary in reverse order because the frames |
| 959 // in the deoptimization translation are ordered bottom-to-top. | 959 // in the deoptimization translation are ordered bottom-to-top. |
| 960 bool is_constructor = IsConstructor(); | 960 bool is_constructor = IsConstructor(); |
| 961 int i = jsframe_count; | 961 int i = jsframe_count; |
| 962 while (i > 0) { | 962 while (i > 0) { |
| 963 opcode = static_cast<Translation::Opcode>(it.Next()); | 963 opcode = static_cast<Translation::Opcode>(it.Next()); |
| 964 if (opcode == Translation::JS_FRAME) { | 964 if (opcode == Translation::JS_FRAME) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 } | 1004 } |
| 1005 | 1005 |
| 1006 Code* code = function->shared()->code(); | 1006 Code* code = function->shared()->code(); |
| 1007 DeoptimizationOutputData* output_data = | 1007 DeoptimizationOutputData* output_data = |
| 1008 DeoptimizationOutputData::cast(code->deoptimization_data()); | 1008 DeoptimizationOutputData::cast(code->deoptimization_data()); |
| 1009 unsigned entry = Deoptimizer::GetOutputInfo(output_data, | 1009 unsigned entry = Deoptimizer::GetOutputInfo(output_data, |
| 1010 ast_id, | 1010 ast_id, |
| 1011 function->shared()); | 1011 function->shared()); |
| 1012 unsigned pc_offset = | 1012 unsigned pc_offset = |
| 1013 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize; | 1013 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize; |
| 1014 ASSERT(pc_offset > 0); | 1014 DCHECK(pc_offset > 0); |
| 1015 | 1015 |
| 1016 FrameSummary summary(receiver, function, code, pc_offset, is_constructor); | 1016 FrameSummary summary(receiver, function, code, pc_offset, is_constructor); |
| 1017 frames->Add(summary); | 1017 frames->Add(summary); |
| 1018 is_constructor = false; | 1018 is_constructor = false; |
| 1019 } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) { | 1019 } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) { |
| 1020 // The next encountered JS_FRAME will be marked as a constructor call. | 1020 // The next encountered JS_FRAME will be marked as a constructor call. |
| 1021 it.Skip(Translation::NumberOfOperandsFor(opcode)); | 1021 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
| 1022 ASSERT(!is_constructor); | 1022 DCHECK(!is_constructor); |
| 1023 is_constructor = true; | 1023 is_constructor = true; |
| 1024 } else { | 1024 } else { |
| 1025 // Skip over operands to advance to the next opcode. | 1025 // Skip over operands to advance to the next opcode. |
| 1026 it.Skip(Translation::NumberOfOperandsFor(opcode)); | 1026 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
| 1027 } | 1027 } |
| 1028 } | 1028 } |
| 1029 ASSERT(!is_constructor); | 1029 DCHECK(!is_constructor); |
| 1030 } | 1030 } |
| 1031 | 1031 |
| 1032 | 1032 |
| 1033 DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData( | 1033 DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData( |
| 1034 int* deopt_index) { | 1034 int* deopt_index) { |
| 1035 ASSERT(is_optimized()); | 1035 DCHECK(is_optimized()); |
| 1036 | 1036 |
| 1037 JSFunction* opt_function = function(); | 1037 JSFunction* opt_function = function(); |
| 1038 Code* code = opt_function->code(); | 1038 Code* code = opt_function->code(); |
| 1039 | 1039 |
| 1040 // The code object may have been replaced by lazy deoptimization. Fall | 1040 // The code object may have been replaced by lazy deoptimization. Fall |
| 1041 // back to a slow search in this case to find the original optimized | 1041 // back to a slow search in this case to find the original optimized |
| 1042 // code object. | 1042 // code object. |
| 1043 if (!code->contains(pc())) { | 1043 if (!code->contains(pc())) { |
| 1044 code = isolate()->inner_pointer_to_code_cache()-> | 1044 code = isolate()->inner_pointer_to_code_cache()-> |
| 1045 GcSafeFindCodeForInnerPointer(pc()); | 1045 GcSafeFindCodeForInnerPointer(pc()); |
| 1046 } | 1046 } |
| 1047 ASSERT(code != NULL); | 1047 DCHECK(code != NULL); |
| 1048 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 1048 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
| 1049 | 1049 |
| 1050 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc()); | 1050 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc()); |
| 1051 *deopt_index = safepoint_entry.deoptimization_index(); | 1051 *deopt_index = safepoint_entry.deoptimization_index(); |
| 1052 ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex); | 1052 DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex); |
| 1053 | 1053 |
| 1054 return DeoptimizationInputData::cast(code->deoptimization_data()); | 1054 return DeoptimizationInputData::cast(code->deoptimization_data()); |
| 1055 } | 1055 } |
| 1056 | 1056 |
| 1057 | 1057 |
| 1058 int OptimizedFrame::GetInlineCount() { | 1058 int OptimizedFrame::GetInlineCount() { |
| 1059 ASSERT(is_optimized()); | 1059 DCHECK(is_optimized()); |
| 1060 | 1060 |
| 1061 // Delegate to JS frame in absence of inlining. | 1061 // Delegate to JS frame in absence of inlining. |
| 1062 // TODO(turbofan): Revisit once we support inlining. | 1062 // TODO(turbofan): Revisit once we support inlining. |
| 1063 if (LookupCode()->is_turbofanned()) { | 1063 if (LookupCode()->is_turbofanned()) { |
| 1064 return JavaScriptFrame::GetInlineCount(); | 1064 return JavaScriptFrame::GetInlineCount(); |
| 1065 } | 1065 } |
| 1066 | 1066 |
| 1067 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 1067 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
| 1068 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); | 1068 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); |
| 1069 | 1069 |
| 1070 TranslationIterator it(data->TranslationByteArray(), | 1070 TranslationIterator it(data->TranslationByteArray(), |
| 1071 data->TranslationIndex(deopt_index)->value()); | 1071 data->TranslationIndex(deopt_index)->value()); |
| 1072 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 1072 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
| 1073 ASSERT(opcode == Translation::BEGIN); | 1073 DCHECK(opcode == Translation::BEGIN); |
| 1074 USE(opcode); | 1074 USE(opcode); |
| 1075 it.Next(); // Drop frame count. | 1075 it.Next(); // Drop frame count. |
| 1076 int jsframe_count = it.Next(); | 1076 int jsframe_count = it.Next(); |
| 1077 return jsframe_count; | 1077 return jsframe_count; |
| 1078 } | 1078 } |
| 1079 | 1079 |
| 1080 | 1080 |
| 1081 void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) { | 1081 void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) { |
| 1082 ASSERT(functions->length() == 0); | 1082 DCHECK(functions->length() == 0); |
| 1083 ASSERT(is_optimized()); | 1083 DCHECK(is_optimized()); |
| 1084 | 1084 |
| 1085 // Delegate to JS frame in absence of inlining. | 1085 // Delegate to JS frame in absence of inlining. |
| 1086 // TODO(turbofan): Revisit once we support inlining. | 1086 // TODO(turbofan): Revisit once we support inlining. |
| 1087 if (LookupCode()->is_turbofanned()) { | 1087 if (LookupCode()->is_turbofanned()) { |
| 1088 return JavaScriptFrame::GetFunctions(functions); | 1088 return JavaScriptFrame::GetFunctions(functions); |
| 1089 } | 1089 } |
| 1090 | 1090 |
| 1091 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 1091 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
| 1092 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); | 1092 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); |
| 1093 FixedArray* literal_array = data->LiteralArray(); | 1093 FixedArray* literal_array = data->LiteralArray(); |
| 1094 | 1094 |
| 1095 TranslationIterator it(data->TranslationByteArray(), | 1095 TranslationIterator it(data->TranslationByteArray(), |
| 1096 data->TranslationIndex(deopt_index)->value()); | 1096 data->TranslationIndex(deopt_index)->value()); |
| 1097 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 1097 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
| 1098 ASSERT(opcode == Translation::BEGIN); | 1098 DCHECK(opcode == Translation::BEGIN); |
| 1099 it.Next(); // Drop frame count. | 1099 it.Next(); // Drop frame count. |
| 1100 int jsframe_count = it.Next(); | 1100 int jsframe_count = it.Next(); |
| 1101 | 1101 |
| 1102 // We insert the frames in reverse order because the frames | 1102 // We insert the frames in reverse order because the frames |
| 1103 // in the deoptimization translation are ordered bottom-to-top. | 1103 // in the deoptimization translation are ordered bottom-to-top. |
| 1104 while (jsframe_count > 0) { | 1104 while (jsframe_count > 0) { |
| 1105 opcode = static_cast<Translation::Opcode>(it.Next()); | 1105 opcode = static_cast<Translation::Opcode>(it.Next()); |
| 1106 if (opcode == Translation::JS_FRAME) { | 1106 if (opcode == Translation::JS_FRAME) { |
| 1107 jsframe_count--; | 1107 jsframe_count--; |
| 1108 it.Next(); // Skip ast id. | 1108 it.Next(); // Skip ast id. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1136 | 1136 |
| 1137 Code* ArgumentsAdaptorFrame::unchecked_code() const { | 1137 Code* ArgumentsAdaptorFrame::unchecked_code() const { |
| 1138 return isolate()->builtins()->builtin( | 1138 return isolate()->builtins()->builtin( |
| 1139 Builtins::kArgumentsAdaptorTrampoline); | 1139 Builtins::kArgumentsAdaptorTrampoline); |
| 1140 } | 1140 } |
| 1141 | 1141 |
| 1142 | 1142 |
| 1143 Code* InternalFrame::unchecked_code() const { | 1143 Code* InternalFrame::unchecked_code() const { |
| 1144 const int offset = InternalFrameConstants::kCodeOffset; | 1144 const int offset = InternalFrameConstants::kCodeOffset; |
| 1145 Object* code = Memory::Object_at(fp() + offset); | 1145 Object* code = Memory::Object_at(fp() + offset); |
| 1146 ASSERT(code != NULL); | 1146 DCHECK(code != NULL); |
| 1147 return reinterpret_cast<Code*>(code); | 1147 return reinterpret_cast<Code*>(code); |
| 1148 } | 1148 } |
| 1149 | 1149 |
| 1150 | 1150 |
| 1151 void StackFrame::PrintIndex(StringStream* accumulator, | 1151 void StackFrame::PrintIndex(StringStream* accumulator, |
| 1152 PrintMode mode, | 1152 PrintMode mode, |
| 1153 int index) { | 1153 int index) { |
| 1154 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index); | 1154 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index); |
| 1155 } | 1155 } |
| 1156 | 1156 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1243 accumulator->Add("\n"); | 1243 accumulator->Add("\n"); |
| 1244 } | 1244 } |
| 1245 | 1245 |
| 1246 // Try to get hold of the context of this frame. | 1246 // Try to get hold of the context of this frame. |
| 1247 Context* context = NULL; | 1247 Context* context = NULL; |
| 1248 if (this->context() != NULL && this->context()->IsContext()) { | 1248 if (this->context() != NULL && this->context()->IsContext()) { |
| 1249 context = Context::cast(this->context()); | 1249 context = Context::cast(this->context()); |
| 1250 } | 1250 } |
| 1251 while (context->IsWithContext()) { | 1251 while (context->IsWithContext()) { |
| 1252 context = context->previous(); | 1252 context = context->previous(); |
| 1253 ASSERT(context != NULL); | 1253 DCHECK(context != NULL); |
| 1254 } | 1254 } |
| 1255 | 1255 |
| 1256 // Print heap-allocated local variables. | 1256 // Print heap-allocated local variables. |
| 1257 if (heap_locals_count > 0) { | 1257 if (heap_locals_count > 0) { |
| 1258 accumulator->Add(" // heap-allocated locals\n"); | 1258 accumulator->Add(" // heap-allocated locals\n"); |
| 1259 } | 1259 } |
| 1260 for (int i = 0; i < heap_locals_count; i++) { | 1260 for (int i = 0; i < heap_locals_count; i++) { |
| 1261 accumulator->Add(" var "); | 1261 accumulator->Add(" var "); |
| 1262 accumulator->PrintName(scope_info->ContextLocalName(i)); | 1262 accumulator->PrintName(scope_info->ContextLocalName(i)); |
| 1263 accumulator->Add(" = "); | 1263 accumulator->Add(" = "); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1324 } | 1324 } |
| 1325 accumulator->Add("\n"); | 1325 accumulator->Add("\n"); |
| 1326 } | 1326 } |
| 1327 | 1327 |
| 1328 accumulator->Add("}\n\n"); | 1328 accumulator->Add("}\n\n"); |
| 1329 } | 1329 } |
| 1330 | 1330 |
| 1331 | 1331 |
| 1332 void EntryFrame::Iterate(ObjectVisitor* v) const { | 1332 void EntryFrame::Iterate(ObjectVisitor* v) const { |
| 1333 StackHandlerIterator it(this, top_handler()); | 1333 StackHandlerIterator it(this, top_handler()); |
| 1334 ASSERT(!it.done()); | 1334 DCHECK(!it.done()); |
| 1335 StackHandler* handler = it.handler(); | 1335 StackHandler* handler = it.handler(); |
| 1336 ASSERT(handler->is_js_entry()); | 1336 DCHECK(handler->is_js_entry()); |
| 1337 handler->Iterate(v, LookupCode()); | 1337 handler->Iterate(v, LookupCode()); |
| 1338 #ifdef DEBUG | 1338 #ifdef DEBUG |
| 1339 // Make sure that the entry frame does not contain more than one | 1339 // Make sure that the entry frame does not contain more than one |
| 1340 // stack handler. | 1340 // stack handler. |
| 1341 it.Advance(); | 1341 it.Advance(); |
| 1342 ASSERT(it.done()); | 1342 DCHECK(it.done()); |
| 1343 #endif | 1343 #endif |
| 1344 IteratePc(v, pc_address(), LookupCode()); | 1344 IteratePc(v, pc_address(), LookupCode()); |
| 1345 } | 1345 } |
| 1346 | 1346 |
| 1347 | 1347 |
| 1348 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { | 1348 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { |
| 1349 const int offset = StandardFrameConstants::kLastObjectOffset; | 1349 const int offset = StandardFrameConstants::kLastObjectOffset; |
| 1350 Object** base = &Memory::Object_at(sp()); | 1350 Object** base = &Memory::Object_at(sp()); |
| 1351 Object** limit = &Memory::Object_at(fp() + offset) + 1; | 1351 Object** limit = &Memory::Object_at(fp() + offset) + 1; |
| 1352 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | 1352 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1412 | 1412 |
| 1413 UNREACHABLE(); | 1413 UNREACHABLE(); |
| 1414 return NULL; | 1414 return NULL; |
| 1415 } | 1415 } |
| 1416 | 1416 |
| 1417 | 1417 |
| 1418 // ------------------------------------------------------------------------- | 1418 // ------------------------------------------------------------------------- |
| 1419 | 1419 |
| 1420 | 1420 |
| 1421 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { | 1421 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { |
| 1422 ASSERT(n >= 0); | 1422 DCHECK(n >= 0); |
| 1423 for (int i = 0; i <= n; i++) { | 1423 for (int i = 0; i <= n; i++) { |
| 1424 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); | 1424 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); |
| 1425 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); | 1425 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); |
| 1426 iterator_.Advance(); | 1426 iterator_.Advance(); |
| 1427 } | 1427 } |
| 1428 UNREACHABLE(); | 1428 UNREACHABLE(); |
| 1429 return NULL; | 1429 return NULL; |
| 1430 } | 1430 } |
| 1431 | 1431 |
| 1432 | 1432 |
| 1433 // ------------------------------------------------------------------------- | 1433 // ------------------------------------------------------------------------- |
| 1434 | 1434 |
| 1435 | 1435 |
| 1436 static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) { | 1436 static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) { |
| 1437 MapWord map_word = object->map_word(); | 1437 MapWord map_word = object->map_word(); |
| 1438 return map_word.IsForwardingAddress() ? | 1438 return map_word.IsForwardingAddress() ? |
| 1439 map_word.ToForwardingAddress()->map() : map_word.ToMap(); | 1439 map_word.ToForwardingAddress()->map() : map_word.ToMap(); |
| 1440 } | 1440 } |
| 1441 | 1441 |
| 1442 | 1442 |
| 1443 static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) { | 1443 static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) { |
| 1444 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object)); | 1444 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object)); |
| 1445 } | 1445 } |
| 1446 | 1446 |
| 1447 | 1447 |
| 1448 #ifdef DEBUG | 1448 #ifdef DEBUG |
| 1449 static bool GcSafeCodeContains(HeapObject* code, Address addr) { | 1449 static bool GcSafeCodeContains(HeapObject* code, Address addr) { |
| 1450 Map* map = GcSafeMapOfCodeSpaceObject(code); | 1450 Map* map = GcSafeMapOfCodeSpaceObject(code); |
| 1451 ASSERT(map == code->GetHeap()->code_map()); | 1451 DCHECK(map == code->GetHeap()->code_map()); |
| 1452 Address start = code->address(); | 1452 Address start = code->address(); |
| 1453 Address end = code->address() + code->SizeFromMap(map); | 1453 Address end = code->address() + code->SizeFromMap(map); |
| 1454 return start <= addr && addr < end; | 1454 return start <= addr && addr < end; |
| 1455 } | 1455 } |
| 1456 #endif | 1456 #endif |
| 1457 | 1457 |
| 1458 | 1458 |
| 1459 Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object, | 1459 Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object, |
| 1460 Address inner_pointer) { | 1460 Address inner_pointer) { |
| 1461 Code* code = reinterpret_cast<Code*>(object); | 1461 Code* code = reinterpret_cast<Code*>(object); |
| 1462 ASSERT(code != NULL && GcSafeCodeContains(code, inner_pointer)); | 1462 DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer)); |
| 1463 return code; | 1463 return code; |
| 1464 } | 1464 } |
| 1465 | 1465 |
| 1466 | 1466 |
| 1467 Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer( | 1467 Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer( |
| 1468 Address inner_pointer) { | 1468 Address inner_pointer) { |
| 1469 Heap* heap = isolate_->heap(); | 1469 Heap* heap = isolate_->heap(); |
| 1470 // Check if the inner pointer points into a large object chunk. | 1470 // Check if the inner pointer points into a large object chunk. |
| 1471 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer); | 1471 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer); |
| 1472 if (large_page != NULL) { | 1472 if (large_page != NULL) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1493 Address next_addr = addr + obj_size; | 1493 Address next_addr = addr + obj_size; |
| 1494 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer); | 1494 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer); |
| 1495 addr = next_addr; | 1495 addr = next_addr; |
| 1496 } | 1496 } |
| 1497 } | 1497 } |
| 1498 | 1498 |
| 1499 | 1499 |
| 1500 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* | 1500 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* |
| 1501 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) { | 1501 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) { |
| 1502 isolate_->counters()->pc_to_code()->Increment(); | 1502 isolate_->counters()->pc_to_code()->Increment(); |
| 1503 ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize)); | 1503 DCHECK(IsPowerOf2(kInnerPointerToCodeCacheSize)); |
| 1504 uint32_t hash = ComputeIntegerHash( | 1504 uint32_t hash = ComputeIntegerHash( |
| 1505 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)), | 1505 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)), |
| 1506 v8::internal::kZeroHashSeed); | 1506 v8::internal::kZeroHashSeed); |
| 1507 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1); | 1507 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1); |
| 1508 InnerPointerToCodeCacheEntry* entry = cache(index); | 1508 InnerPointerToCodeCacheEntry* entry = cache(index); |
| 1509 if (entry->inner_pointer == inner_pointer) { | 1509 if (entry->inner_pointer == inner_pointer) { |
| 1510 isolate_->counters()->pc_to_code_cached()->Increment(); | 1510 isolate_->counters()->pc_to_code_cached()->Increment(); |
| 1511 ASSERT(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer)); | 1511 DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer)); |
| 1512 } else { | 1512 } else { |
| 1513 // Because this code may be interrupted by a profiling signal that | 1513 // Because this code may be interrupted by a profiling signal that |
| 1514 // also queries the cache, we cannot update inner_pointer before the code | 1514 // also queries the cache, we cannot update inner_pointer before the code |
| 1515 // has been set. Otherwise, we risk trying to use a cache entry before | 1515 // has been set. Otherwise, we risk trying to use a cache entry before |
| 1516 // the code has been computed. | 1516 // the code has been computed. |
| 1517 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer); | 1517 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer); |
| 1518 entry->safepoint_entry.Reset(); | 1518 entry->safepoint_entry.Reset(); |
| 1519 entry->inner_pointer = inner_pointer; | 1519 entry->inner_pointer = inner_pointer; |
| 1520 } | 1520 } |
| 1521 return entry; | 1521 return entry; |
| 1522 } | 1522 } |
| 1523 | 1523 |
| 1524 | 1524 |
| 1525 // ------------------------------------------------------------------------- | 1525 // ------------------------------------------------------------------------- |
| 1526 | 1526 |
| 1527 | 1527 |
| 1528 void StackHandler::Unwind(Isolate* isolate, | 1528 void StackHandler::Unwind(Isolate* isolate, |
| 1529 FixedArray* array, | 1529 FixedArray* array, |
| 1530 int offset, | 1530 int offset, |
| 1531 int previous_handler_offset) const { | 1531 int previous_handler_offset) const { |
| 1532 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5); | 1532 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5); |
| 1533 ASSERT_LE(0, offset); | 1533 DCHECK_LE(0, offset); |
| 1534 ASSERT_GE(array->length(), offset + StackHandlerConstants::kSlotCount); | 1534 DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount); |
| 1535 // Unwinding a stack handler into an array chains it in the opposite | 1535 // Unwinding a stack handler into an array chains it in the opposite |
| 1536 // direction, re-using the "next" slot as a "previous" link, so that stack | 1536 // direction, re-using the "next" slot as a "previous" link, so that stack |
| 1537 // handlers can be later re-wound in the correct order. Decode the "state" | 1537 // handlers can be later re-wound in the correct order. Decode the "state" |
| 1538 // slot into "index" and "kind" and store them separately, using the fp slot. | 1538 // slot into "index" and "kind" and store them separately, using the fp slot. |
| 1539 array->set(offset, Smi::FromInt(previous_handler_offset)); // next | 1539 array->set(offset, Smi::FromInt(previous_handler_offset)); // next |
| 1540 array->set(offset + 1, *code_address()); // code | 1540 array->set(offset + 1, *code_address()); // code |
| 1541 array->set(offset + 2, Smi::FromInt(static_cast<int>(index()))); // state | 1541 array->set(offset + 2, Smi::FromInt(static_cast<int>(index()))); // state |
| 1542 array->set(offset + 3, *context_address()); // context | 1542 array->set(offset + 3, *context_address()); // context |
| 1543 array->set(offset + 4, Smi::FromInt(static_cast<int>(kind()))); // fp | 1543 array->set(offset + 4, Smi::FromInt(static_cast<int>(kind()))); // fp |
| 1544 | 1544 |
| 1545 *isolate->handler_address() = next()->address(); | 1545 *isolate->handler_address() = next()->address(); |
| 1546 } | 1546 } |
| 1547 | 1547 |
| 1548 | 1548 |
| 1549 int StackHandler::Rewind(Isolate* isolate, | 1549 int StackHandler::Rewind(Isolate* isolate, |
| 1550 FixedArray* array, | 1550 FixedArray* array, |
| 1551 int offset, | 1551 int offset, |
| 1552 Address fp) { | 1552 Address fp) { |
| 1553 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5); | 1553 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5); |
| 1554 ASSERT_LE(0, offset); | 1554 DCHECK_LE(0, offset); |
| 1555 ASSERT_GE(array->length(), offset + StackHandlerConstants::kSlotCount); | 1555 DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount); |
| 1556 Smi* prev_handler_offset = Smi::cast(array->get(offset)); | 1556 Smi* prev_handler_offset = Smi::cast(array->get(offset)); |
| 1557 Code* code = Code::cast(array->get(offset + 1)); | 1557 Code* code = Code::cast(array->get(offset + 1)); |
| 1558 Smi* smi_index = Smi::cast(array->get(offset + 2)); | 1558 Smi* smi_index = Smi::cast(array->get(offset + 2)); |
| 1559 Object* context = array->get(offset + 3); | 1559 Object* context = array->get(offset + 3); |
| 1560 Smi* smi_kind = Smi::cast(array->get(offset + 4)); | 1560 Smi* smi_kind = Smi::cast(array->get(offset + 4)); |
| 1561 | 1561 |
| 1562 unsigned state = KindField::encode(static_cast<Kind>(smi_kind->value())) | | 1562 unsigned state = KindField::encode(static_cast<Kind>(smi_kind->value())) | |
| 1563 IndexField::encode(static_cast<unsigned>(smi_index->value())); | 1563 IndexField::encode(static_cast<unsigned>(smi_index->value())); |
| 1564 | 1564 |
| 1565 Memory::Address_at(address() + StackHandlerConstants::kNextOffset) = | 1565 Memory::Address_at(address() + StackHandlerConstants::kNextOffset) = |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1588 }; | 1588 }; |
| 1589 | 1589 |
| 1590 JSCallerSavedCodeData caller_saved_code_data; | 1590 JSCallerSavedCodeData caller_saved_code_data; |
| 1591 | 1591 |
| 1592 void SetUpJSCallerSavedCodeData() { | 1592 void SetUpJSCallerSavedCodeData() { |
| 1593 int i = 0; | 1593 int i = 0; |
| 1594 for (int r = 0; r < kNumRegs; r++) | 1594 for (int r = 0; r < kNumRegs; r++) |
| 1595 if ((kJSCallerSaved & (1 << r)) != 0) | 1595 if ((kJSCallerSaved & (1 << r)) != 0) |
| 1596 caller_saved_code_data.reg_code[i++] = r; | 1596 caller_saved_code_data.reg_code[i++] = r; |
| 1597 | 1597 |
| 1598 ASSERT(i == kNumJSCallerSaved); | 1598 DCHECK(i == kNumJSCallerSaved); |
| 1599 } | 1599 } |
| 1600 | 1600 |
| 1601 | 1601 |
| 1602 int JSCallerSavedCode(int n) { | 1602 int JSCallerSavedCode(int n) { |
| 1603 ASSERT(0 <= n && n < kNumJSCallerSaved); | 1603 DCHECK(0 <= n && n < kNumJSCallerSaved); |
| 1604 return caller_saved_code_data.reg_code[n]; | 1604 return caller_saved_code_data.reg_code[n]; |
| 1605 } | 1605 } |
| 1606 | 1606 |
| 1607 | 1607 |
| 1608 #define DEFINE_WRAPPER(type, field) \ | 1608 #define DEFINE_WRAPPER(type, field) \ |
| 1609 class field##_Wrapper : public ZoneObject { \ | 1609 class field##_Wrapper : public ZoneObject { \ |
| 1610 public: /* NOLINT */ \ | 1610 public: /* NOLINT */ \ |
| 1611 field##_Wrapper(const field& original) : frame_(original) { \ | 1611 field##_Wrapper(const field& original) : frame_(original) { \ |
| 1612 } \ | 1612 } \ |
| 1613 field frame_; \ | 1613 field frame_; \ |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1636 ZoneList<StackFrame*> list(10, zone); | 1636 ZoneList<StackFrame*> list(10, zone); |
| 1637 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1637 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
| 1638 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1638 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
| 1639 list.Add(frame, zone); | 1639 list.Add(frame, zone); |
| 1640 } | 1640 } |
| 1641 return list.ToVector(); | 1641 return list.ToVector(); |
| 1642 } | 1642 } |
| 1643 | 1643 |
| 1644 | 1644 |
| 1645 } } // namespace v8::internal | 1645 } } // namespace v8::internal |
| OLD | NEW |