| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/frames.h" | 5 #include "src/frames.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/v8.h" | 9 #include "src/v8.h" |
| 10 | 10 |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 SingletonFor(frame->GetCallerState(&state)) != NULL; | 314 SingletonFor(frame->GetCallerState(&state)) != NULL; |
| 315 } | 315 } |
| 316 | 316 |
| 317 | 317 |
| 318 bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const { | 318 bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const { |
| 319 if (!IsValidStackAddress(fp)) return false; | 319 if (!IsValidStackAddress(fp)) return false; |
| 320 Address sp = ExitFrame::ComputeStackPointer(fp); | 320 Address sp = ExitFrame::ComputeStackPointer(fp); |
| 321 if (!IsValidStackAddress(sp)) return false; | 321 if (!IsValidStackAddress(sp)) return false; |
| 322 StackFrame::State state; | 322 StackFrame::State state; |
| 323 ExitFrame::FillState(fp, sp, &state); | 323 ExitFrame::FillState(fp, sp, &state); |
| 324 if (!IsValidStackAddress(reinterpret_cast<Address>(state.pc_address))) { | |
| 325 return false; | |
| 326 } | |
| 327 return *state.pc_address != NULL; | 324 return *state.pc_address != NULL; |
| 328 } | 325 } |
| 329 | 326 |
| 330 | 327 |
| 331 void SafeStackFrameIterator::Advance() { | 328 void SafeStackFrameIterator::Advance() { |
| 332 while (true) { | 329 while (true) { |
| 333 AdvanceOneFrame(); | 330 AdvanceOneFrame(); |
| 334 if (done()) return; | 331 if (done()) return; |
| 335 if (frame_->is_java_script()) return; | 332 if (frame_->is_java_script()) return; |
| 336 if (frame_->is_exit() && external_callback_scope_) { | 333 if (frame_->is_exit() && external_callback_scope_) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 *stack_slots = code->stack_slots(); | 375 *stack_slots = code->stack_slots(); |
| 379 return code; | 376 return code; |
| 380 } | 377 } |
| 381 | 378 |
| 382 | 379 |
| 383 #ifdef DEBUG | 380 #ifdef DEBUG |
| 384 static bool GcSafeCodeContains(HeapObject* object, Address addr); | 381 static bool GcSafeCodeContains(HeapObject* object, Address addr); |
| 385 #endif | 382 #endif |
| 386 | 383 |
| 387 | 384 |
| 388 void StackFrame::IteratePc(ObjectVisitor* v, | 385 void StackFrame::IteratePc(ObjectVisitor* v, Address* pc_address, |
| 389 Address* pc_address, | 386 Address* constant_pool_address, Code* holder) { |
| 390 Code* holder) { | |
| 391 Address pc = *pc_address; | 387 Address pc = *pc_address; |
| 392 DCHECK(GcSafeCodeContains(holder, pc)); | 388 DCHECK(GcSafeCodeContains(holder, pc)); |
| 393 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start()); | 389 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start()); |
| 394 Object* code = holder; | 390 Object* code = holder; |
| 395 v->VisitPointer(&code); | 391 v->VisitPointer(&code); |
| 396 if (code != holder) { | 392 if (code != holder) { |
| 397 holder = reinterpret_cast<Code*>(code); | 393 holder = reinterpret_cast<Code*>(code); |
| 398 pc = holder->instruction_start() + pc_offset; | 394 pc = holder->instruction_start() + pc_offset; |
| 399 *pc_address = pc; | 395 *pc_address = pc; |
| 396 if (FLAG_enable_embedded_constant_pool && constant_pool_address) { |
| 397 *constant_pool_address = holder->constant_pool(); |
| 398 } |
| 400 } | 399 } |
| 401 } | 400 } |
| 402 | 401 |
| 403 | 402 |
| 404 void StackFrame::SetReturnAddressLocationResolver( | 403 void StackFrame::SetReturnAddressLocationResolver( |
| 405 ReturnAddressLocationResolver resolver) { | 404 ReturnAddressLocationResolver resolver) { |
| 406 DCHECK(return_address_location_resolver_ == NULL); | 405 DCHECK(return_address_location_resolver_ == NULL); |
| 407 return_address_location_resolver_ = resolver; | 406 return_address_location_resolver_ = resolver; |
| 408 } | 407 } |
| 409 | 408 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 return reinterpret_cast<Code*>(code_slot()); | 498 return reinterpret_cast<Code*>(code_slot()); |
| 500 } | 499 } |
| 501 | 500 |
| 502 | 501 |
| 503 void ExitFrame::ComputeCallerState(State* state) const { | 502 void ExitFrame::ComputeCallerState(State* state) const { |
| 504 // Set up the caller state. | 503 // Set up the caller state. |
| 505 state->sp = caller_sp(); | 504 state->sp = caller_sp(); |
| 506 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); | 505 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); |
| 507 state->pc_address = ResolveReturnAddressLocation( | 506 state->pc_address = ResolveReturnAddressLocation( |
| 508 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset)); | 507 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset)); |
| 509 if (FLAG_enable_ool_constant_pool) { | 508 if (FLAG_enable_embedded_constant_pool) { |
| 510 state->constant_pool_address = reinterpret_cast<Address*>( | 509 state->constant_pool_address = reinterpret_cast<Address*>( |
| 511 fp() + ExitFrameConstants::kConstantPoolOffset); | 510 fp() + ExitFrameConstants::kConstantPoolOffset); |
| 512 } | 511 } |
| 513 } | 512 } |
| 514 | 513 |
| 515 | 514 |
| 516 void ExitFrame::SetCallerFp(Address caller_fp) { | 515 void ExitFrame::SetCallerFp(Address caller_fp) { |
| 517 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp; | 516 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp; |
| 518 } | 517 } |
| 519 | 518 |
| 520 | 519 |
| 521 void ExitFrame::Iterate(ObjectVisitor* v) const { | 520 void ExitFrame::Iterate(ObjectVisitor* v) const { |
| 522 // The arguments are traversed as part of the expression stack of | 521 // The arguments are traversed as part of the expression stack of |
| 523 // the calling frame. | 522 // the calling frame. |
| 524 IteratePc(v, pc_address(), LookupCode()); | 523 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); |
| 525 v->VisitPointer(&code_slot()); | 524 v->VisitPointer(&code_slot()); |
| 526 if (FLAG_enable_ool_constant_pool) { | |
| 527 v->VisitPointer(&constant_pool_slot()); | |
| 528 } | |
| 529 } | 525 } |
| 530 | 526 |
| 531 | 527 |
| 532 Address ExitFrame::GetCallerStackPointer() const { | 528 Address ExitFrame::GetCallerStackPointer() const { |
| 533 return fp() + ExitFrameConstants::kCallerSPDisplacement; | 529 return fp() + ExitFrameConstants::kCallerSPDisplacement; |
| 534 } | 530 } |
| 535 | 531 |
| 536 | 532 |
| 537 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { | 533 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { |
| 538 if (fp == 0) return NONE; | 534 if (fp == 0) return NONE; |
| 539 Address sp = ComputeStackPointer(fp); | 535 Address sp = ComputeStackPointer(fp); |
| 540 FillState(fp, sp, state); | 536 FillState(fp, sp, state); |
| 541 DCHECK(*state->pc_address != NULL); | 537 DCHECK(*state->pc_address != NULL); |
| 542 return EXIT; | 538 return EXIT; |
| 543 } | 539 } |
| 544 | 540 |
| 545 | 541 |
| 546 Address ExitFrame::ComputeStackPointer(Address fp) { | 542 Address ExitFrame::ComputeStackPointer(Address fp) { |
| 547 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset); | 543 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset); |
| 548 } | 544 } |
| 549 | 545 |
| 550 | 546 |
| 551 void ExitFrame::FillState(Address fp, Address sp, State* state) { | 547 void ExitFrame::FillState(Address fp, Address sp, State* state) { |
| 552 state->sp = sp; | 548 state->sp = sp; |
| 553 state->fp = fp; | 549 state->fp = fp; |
| 554 state->pc_address = ResolveReturnAddressLocation( | 550 state->pc_address = ResolveReturnAddressLocation( |
| 555 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize)); | 551 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize)); |
| 556 state->constant_pool_address = | 552 // The constant pool recorded in the exit frame is not associated |
| 557 reinterpret_cast<Address*>(fp + ExitFrameConstants::kConstantPoolOffset); | 553 // with the pc in this state (the return address into a C entry |
| 554 // stub). ComputeCallerState will retrieve the constant pool |
| 555 // together with the associated caller pc. |
| 556 state->constant_pool_address = NULL; |
| 558 } | 557 } |
| 559 | 558 |
| 560 | 559 |
| 561 Address StandardFrame::GetExpressionAddress(int n) const { | 560 Address StandardFrame::GetExpressionAddress(int n) const { |
| 562 const int offset = StandardFrameConstants::kExpressionsOffset; | 561 const int offset = StandardFrameConstants::kExpressionsOffset; |
| 563 return fp() + offset - n * kPointerSize; | 562 return fp() + offset - n * kPointerSize; |
| 564 } | 563 } |
| 565 | 564 |
| 566 | 565 |
| 567 Object* StandardFrame::GetExpression(Address fp, int index) { | 566 Object* StandardFrame::GetExpression(Address fp, int index) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 // Visit pointer spill slots and locals. | 655 // Visit pointer spill slots and locals. |
| 657 for (unsigned index = 0; index < stack_slots; index++) { | 656 for (unsigned index = 0; index < stack_slots; index++) { |
| 658 int byte_index = index >> kBitsPerByteLog2; | 657 int byte_index = index >> kBitsPerByteLog2; |
| 659 int bit_index = index & (kBitsPerByte - 1); | 658 int bit_index = index & (kBitsPerByte - 1); |
| 660 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) { | 659 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) { |
| 661 v->VisitPointer(parameters_limit + index); | 660 v->VisitPointer(parameters_limit + index); |
| 662 } | 661 } |
| 663 } | 662 } |
| 664 | 663 |
| 665 // Visit the return address in the callee and incoming arguments. | 664 // Visit the return address in the callee and incoming arguments. |
| 666 IteratePc(v, pc_address(), code); | 665 IteratePc(v, pc_address(), constant_pool_address(), code); |
| 667 | 666 |
| 668 // Visit the context in stub frame and JavaScript frame. | 667 // Visit the context in stub frame and JavaScript frame. |
| 669 // Visit the function in JavaScript frame. | 668 // Visit the function in JavaScript frame. |
| 670 Object** fixed_base = &Memory::Object_at( | 669 Object** fixed_base = &Memory::Object_at( |
| 671 fp() + StandardFrameConstants::kMarkerOffset); | 670 fp() + StandardFrameConstants::kMarkerOffset); |
| 672 Object** fixed_limit = &Memory::Object_at(fp()); | 671 Object** fixed_limit = &Memory::Object_at(fp()); |
| 673 v->VisitPointers(fixed_base, fixed_limit); | 672 v->VisitPointers(fixed_base, fixed_limit); |
| 674 } | 673 } |
| 675 | 674 |
| 676 | 675 |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1283 accumulator->Add(" // not passed to callee"); | 1282 accumulator->Add(" // not passed to callee"); |
| 1284 } | 1283 } |
| 1285 accumulator->Add("\n"); | 1284 accumulator->Add("\n"); |
| 1286 } | 1285 } |
| 1287 | 1286 |
| 1288 accumulator->Add("}\n\n"); | 1287 accumulator->Add("}\n\n"); |
| 1289 } | 1288 } |
| 1290 | 1289 |
| 1291 | 1290 |
| 1292 void EntryFrame::Iterate(ObjectVisitor* v) const { | 1291 void EntryFrame::Iterate(ObjectVisitor* v) const { |
| 1293 IteratePc(v, pc_address(), LookupCode()); | 1292 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); |
| 1294 } | 1293 } |
| 1295 | 1294 |
| 1296 | 1295 |
| 1297 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { | 1296 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { |
| 1298 const int offset = StandardFrameConstants::kLastObjectOffset; | 1297 const int offset = StandardFrameConstants::kLastObjectOffset; |
| 1299 Object** base = &Memory::Object_at(sp()); | 1298 Object** base = &Memory::Object_at(sp()); |
| 1300 Object** limit = &Memory::Object_at(fp() + offset) + 1; | 1299 Object** limit = &Memory::Object_at(fp() + offset) + 1; |
| 1301 v->VisitPointers(base, limit); | 1300 v->VisitPointers(base, limit); |
| 1302 } | 1301 } |
| 1303 | 1302 |
| 1304 | 1303 |
| 1305 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { | 1304 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { |
| 1306 IterateExpressions(v); | 1305 IterateExpressions(v); |
| 1307 IteratePc(v, pc_address(), LookupCode()); | 1306 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); |
| 1308 } | 1307 } |
| 1309 | 1308 |
| 1310 | 1309 |
| 1311 void InternalFrame::Iterate(ObjectVisitor* v) const { | 1310 void InternalFrame::Iterate(ObjectVisitor* v) const { |
| 1312 // Internal frames only have object pointers on the expression stack | 1311 // Internal frames only have object pointers on the expression stack |
| 1313 // as they never have any arguments. | 1312 // as they never have any arguments. |
| 1314 IterateExpressions(v); | 1313 IterateExpressions(v); |
| 1315 IteratePc(v, pc_address(), LookupCode()); | 1314 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); |
| 1316 } | 1315 } |
| 1317 | 1316 |
| 1318 | 1317 |
| 1319 void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const { | 1318 void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const { |
| 1320 Object** base = &Memory::Object_at(sp()); | 1319 Object** base = &Memory::Object_at(sp()); |
| 1321 Object** limit = &Memory::Object_at(fp() + | 1320 Object** limit = &Memory::Object_at(fp() + |
| 1322 kFirstRegisterParameterFrameOffset); | 1321 kFirstRegisterParameterFrameOffset); |
| 1323 v->VisitPointers(base, limit); | 1322 v->VisitPointers(base, limit); |
| 1324 base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset); | 1323 base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset); |
| 1325 const int offset = StandardFrameConstants::kLastObjectOffset; | 1324 const int offset = StandardFrameConstants::kLastObjectOffset; |
| 1326 limit = &Memory::Object_at(fp() + offset) + 1; | 1325 limit = &Memory::Object_at(fp() + offset) + 1; |
| 1327 v->VisitPointers(base, limit); | 1326 v->VisitPointers(base, limit); |
| 1328 IteratePc(v, pc_address(), LookupCode()); | 1327 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); |
| 1329 } | 1328 } |
| 1330 | 1329 |
| 1331 | 1330 |
| 1332 Address StubFailureTrampolineFrame::GetCallerStackPointer() const { | 1331 Address StubFailureTrampolineFrame::GetCallerStackPointer() const { |
| 1333 return fp() + StandardFrameConstants::kCallerSPOffset; | 1332 return fp() + StandardFrameConstants::kCallerSPOffset; |
| 1334 } | 1333 } |
| 1335 | 1334 |
| 1336 | 1335 |
| 1337 Code* StubFailureTrampolineFrame::unchecked_code() const { | 1336 Code* StubFailureTrampolineFrame::unchecked_code() const { |
| 1338 Code* trampoline; | 1337 Code* trampoline; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1520 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1519 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
| 1521 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1520 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
| 1522 list.Add(frame, zone); | 1521 list.Add(frame, zone); |
| 1523 } | 1522 } |
| 1524 return list.ToVector(); | 1523 return list.ToVector(); |
| 1525 } | 1524 } |
| 1526 | 1525 |
| 1527 | 1526 |
| 1528 } // namespace internal | 1527 } // namespace internal |
| 1529 } // namespace v8 | 1528 } // namespace v8 |
| OLD | NEW |