Chromium Code Reviews| Index: src/frames.cc |
| diff --git a/src/frames.cc b/src/frames.cc |
| index aaf8c79e23256a12d4d3a7fe7bce939f9f604ff8..aff389532da15768571b8d3cfa9a1fea74fe1092 100644 |
| --- a/src/frames.cc |
| +++ b/src/frames.cc |
| @@ -840,6 +840,77 @@ 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()); |
| + const int kStackHandlerSlotCount = |
|
Michael Starzinger
2013/05/07 09:55:44
Move the "kStackHandlerSlotCount" constant into th
|
| + (StackHandlerConstants::kSize >> kPointerSizeLog2); |
| + 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, kStackHandlerSlotCount); |
| + ASSERT_EQ(handler->address(), GetOperandSlot(i)); |
| + int next_stack_handler_index = i + 1 - kStackHandlerSlotCount; |
| + handler->Unwind(isolate(), store, next_stack_handler_index, |
| + Smi::FromInt(*stack_handler_index)); |
| + *stack_handler_index = next_stack_handler_index; |
| + i -= kStackHandlerSlotCount; |
| + } |
| + |
| + // 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; |
| + const int kStackHandlerSlotCount = |
|
Michael Starzinger
2013/05/07 09:55:44
Likewise.
|
| + (StackHandlerConstants::kSize >> kPointerSizeLog2); |
| + 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 + kStackHandlerSlotCount - 1; |
| + StackHandler *handler = |
| + StackHandler::FromAddress(GetOperandSlot(handler_slot_index)); |
| + Object *data = handler->Rewind(isolate(), store, i, fp()); |
| + stack_handler_index = Smi::cast(data)->value(); |
| + i += kStackHandlerSlotCount; |
| + } |
| + } |
| + |
| + 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 +1509,59 @@ InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* |
| // ------------------------------------------------------------------------- |
| + |
| +void StackHandler::Unwind(Isolate* isolate, FixedArray* array, int offset, |
|
Michael Starzinger
2013/05/07 09:55:44
style: Better put each argument on a single line,
|
| + Object* data) const { |
| + STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| + ASSERT_LE(0, offset); |
| + ASSERT_GE(array->length(), offset + 5); |
| + array->set(offset, data); // next |
| + array->set(offset + 1, *code_address()); // code |
| + uintptr_t state = |
| + Memory::uintptr_at(address() + StackHandlerConstants::kStateOffset); |
| + // Convert state to 31-bit signed integer, so it fits in a Smi. |
| + ASSERT(state < (1U << (32 - kSmiTagSize))); |
| + int int_state = static_cast<int>(state << kSmiTagSize) >> kSmiTagSize; |
| + Smi *smi_state = Smi::FromInt(int_state); |
| + array->set(offset + 2, smi_state); // state |
| + array->set(offset + 3, *context_address()); // context |
| + array->set(offset + 4, Smi::FromInt(0)); // fp |
| + |
| + *isolate->handler_address() = next()->address(); |
| +} |
| + |
| + |
| +Object* StackHandler::Rewind(Isolate* isolate, FixedArray* array, int offset, |
|
Michael Starzinger
2013/05/07 09:55:44
style: Likewise.
|
| + Address fp) { |
| + STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| + ASSERT_LE(0, offset); |
| + ASSERT_GE(array->length(), offset + 5); |
| + Object *data = array->get(offset); |
| + Code *code = Code::cast(array->get(offset + 1)); |
| + Smi *smi_state = Smi::cast(array->get(offset + 2)); |
| + int int_state = smi_state->value(); |
| + // Convert saved state from Smi to 31-bit unsigned integer. |
| + unsigned state = |
| + static_cast<unsigned>(int_state << kSmiTagSize) >> kSmiTagSize; |
|
Michael Starzinger
2013/05/07 09:55:44
I think this conversion is broken on 64-bit system
|
| + Object *context = array->get(offset + 3); |
| + ASSERT_EQ(Smi::FromInt(0), array->get(offset + 4)); |
| + |
| + Memory::Address_at(address() + StackHandlerConstants::kNextOffset) = |
| + *isolate->handler_address(); |
|
Michael Starzinger
2013/05/07 09:55:44
nit: Indentation is off.
|
| + 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 data; |
| +} |
| + |
| + |
| +// ------------------------------------------------------------------------- |
| + |
| int NumRegs(RegList reglist) { |
| return CompilerIntrinsics::CountSetBits(reglist); |
| } |