| Index: src/frames.cc
|
| diff --git a/src/frames.cc b/src/frames.cc
|
| index aaf8c79e23256a12d4d3a7fe7bce939f9f604ff8..152cd30d5b125789da857ca98abb3dd7d914d087 100644
|
| --- a/src/frames.cc
|
| +++ b/src/frames.cc
|
| @@ -840,6 +840,72 @@ void JavaScriptFrame::PrintTop(Isolate* isolate,
|
| }
|
|
|
|
|
| +void JavaScriptFrame::SaveOperandStack(FixedArray* store,
|
| + int* stack_handler_index) const {
|
| + int operands_count = store->length();
|
| + ASSERT_LE(operands_count, ComputeOperandsCount());
|
| +
|
| + // Visit the stack in LIFO order, saving operands and stack handlers into the
|
| + // array. The saved stack handlers store a link to the next stack handler,
|
| + // which will allow RestoreOperandStack to rewind the handlers.
|
| + StackHandlerIterator it(this, top_handler());
|
| + int i = operands_count - 1;
|
| + *stack_handler_index = -1;
|
| + for (; !it.done(); it.Advance()) {
|
| + StackHandler* handler = it.handler();
|
| + // Save operands pushed after the handler was pushed.
|
| + for (; GetOperandSlot(i) < handler->address(); i--) {
|
| + store->set(i, GetOperand(i));
|
| + }
|
| + ASSERT_GE(i + 1, StackHandlerConstants::kSlotCount);
|
| + ASSERT_EQ(handler->address(), GetOperandSlot(i));
|
| + int next_stack_handler_index = i + 1 - StackHandlerConstants::kSlotCount;
|
| + handler->Unwind(isolate(), store, next_stack_handler_index,
|
| + *stack_handler_index);
|
| + *stack_handler_index = next_stack_handler_index;
|
| + i -= StackHandlerConstants::kSlotCount;
|
| + }
|
| +
|
| + // Save any remaining operands.
|
| + for (; i >= 0; i--) {
|
| + store->set(i, GetOperand(i));
|
| + }
|
| +}
|
| +
|
| +
|
| +void JavaScriptFrame::RestoreOperandStack(FixedArray* store,
|
| + int stack_handler_index) {
|
| + int operands_count = store->length();
|
| + ASSERT_LE(operands_count, ComputeOperandsCount());
|
| + int i = 0;
|
| + while (i <= stack_handler_index) {
|
| + if (i < stack_handler_index) {
|
| + // An operand.
|
| + ASSERT_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
|
| + Memory::Object_at(GetOperandSlot(i)) = store->get(i);
|
| + i++;
|
| + } else {
|
| + // A stack handler.
|
| + ASSERT_EQ(i, stack_handler_index);
|
| + // The FixedArray store grows up. The stack grows down. So the operand
|
| + // slot for i actually points to the bottom of the top word in the
|
| + // handler. The base of the StackHandler* is the address of the bottom
|
| + // word, which will be the last slot that is in the handler.
|
| + int handler_slot_index = i + StackHandlerConstants::kSlotCount - 1;
|
| + StackHandler *handler =
|
| + StackHandler::FromAddress(GetOperandSlot(handler_slot_index));
|
| + stack_handler_index = handler->Rewind(isolate(), store, i, fp());
|
| + i += StackHandlerConstants::kSlotCount;
|
| + }
|
| + }
|
| +
|
| + for (; i < operands_count; i++) {
|
| + ASSERT_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
|
| + Memory::Object_at(GetOperandSlot(i)) = store->get(i);
|
| + }
|
| +}
|
| +
|
| +
|
| void FrameSummary::Print() {
|
| PrintF("receiver: ");
|
| receiver_->ShortPrint();
|
| @@ -1438,6 +1504,60 @@ InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
|
|
|
| // -------------------------------------------------------------------------
|
|
|
| +
|
| +void StackHandler::Unwind(Isolate* isolate,
|
| + FixedArray* array,
|
| + int offset,
|
| + int previous_handler_offset) const {
|
| + STATIC_ASSERT(StackHandlerConstants::kSlotCount == 5);
|
| + ASSERT_LE(0, offset);
|
| + ASSERT_GE(array->length(), offset + 5);
|
| + // Unwinding a stack handler into an array chains it in the opposite
|
| + // direction, re-using the "next" slot as a "previous" link, so that stack
|
| + // handlers can be later re-wound in the correct order. Decode the "state"
|
| + // slot into "index" and "kind" and store them separately, using the fp slot.
|
| + array->set(offset, Smi::FromInt(previous_handler_offset)); // next
|
| + array->set(offset + 1, *code_address()); // code
|
| + array->set(offset + 2, Smi::FromInt(static_cast<int>(index()))); // state
|
| + array->set(offset + 3, *context_address()); // context
|
| + array->set(offset + 4, Smi::FromInt(static_cast<int>(kind()))); // fp
|
| +
|
| + *isolate->handler_address() = next()->address();
|
| +}
|
| +
|
| +
|
| +int StackHandler::Rewind(Isolate* isolate,
|
| + FixedArray* array,
|
| + int offset,
|
| + Address fp) {
|
| + STATIC_ASSERT(StackHandlerConstants::kSlotCount == 5);
|
| + ASSERT_LE(0, offset);
|
| + ASSERT_GE(array->length(), offset + 5);
|
| + Smi* prev_handler_offset = Smi::cast(array->get(offset));
|
| + Code* code = Code::cast(array->get(offset + 1));
|
| + Smi* smi_index = Smi::cast(array->get(offset + 2));
|
| + Object* context = array->get(offset + 3);
|
| + Smi* smi_kind = Smi::cast(array->get(offset + 4));
|
| +
|
| + unsigned state = KindField::encode(static_cast<Kind>(smi_kind->value())) |
|
| + IndexField::encode(static_cast<unsigned>(smi_index->value()));
|
| +
|
| + Memory::Address_at(address() + StackHandlerConstants::kNextOffset) =
|
| + *isolate->handler_address();
|
| + Memory::Object_at(address() + StackHandlerConstants::kCodeOffset) = code;
|
| + Memory::uintptr_at(address() + StackHandlerConstants::kStateOffset) = state;
|
| + Memory::Object_at(address() + StackHandlerConstants::kContextOffset) =
|
| + context;
|
| + Memory::Address_at(address() + StackHandlerConstants::kFPOffset) = fp;
|
| +
|
| + *isolate->handler_address() = address();
|
| +
|
| + return prev_handler_offset->value();
|
| +}
|
| +
|
| +
|
| +// -------------------------------------------------------------------------
|
| +
|
| int NumRegs(RegList reglist) {
|
| return CompilerIntrinsics::CountSetBits(reglist);
|
| }
|
|
|