| Index: src/accessors.cc
|
| diff --git a/src/accessors.cc b/src/accessors.cc
|
| index 4e724678b60785755d2bf0483e0590e432fb83dc..89e0b95610fffbafc6ce0fc002418b1b78230425 100644
|
| --- a/src/accessors.cc
|
| +++ b/src/accessors.cc
|
| @@ -568,6 +568,172 @@ const AccessorDescriptor Accessors::FunctionName = {
|
| // Accessors::FunctionArguments
|
| //
|
|
|
| +static Address SlotAddress(JavaScriptFrame* frame, int slot_index) {
|
| + if (slot_index >= 0) {
|
| + const int offset = JavaScriptFrameConstants::kLocal0Offset;
|
| + return frame->fp() + offset - (slot_index * kPointerSize);
|
| + } else {
|
| + const int offset = JavaScriptFrameConstants::kReceiverOffset;
|
| + return frame->caller_sp() + offset + (slot_index * kPointerSize);
|
| + }
|
| +}
|
| +
|
| +
|
| +// We can't intermix stack decoding and allocations because
|
| +// deoptimization infrastracture is not GC safe.
|
| +// Thus we build a temporary structure in malloced space.
|
| +class SlotRef BASE_EMBEDDED {
|
| + public:
|
| + enum SlotRepresentation {
|
| + UNKNOWN,
|
| + TAGGED,
|
| + INT32,
|
| + DOUBLE,
|
| + LITERAL
|
| + };
|
| +
|
| + SlotRef()
|
| + : addr_(NULL), representation_(UNKNOWN) { }
|
| +
|
| + SlotRef(Address addr, SlotRepresentation representation)
|
| + : addr_(addr), representation_(representation) { }
|
| +
|
| + explicit SlotRef(Object* literal)
|
| + : literal_(literal), representation_(LITERAL) { }
|
| +
|
| + Handle<Object> GetValue() {
|
| + switch (representation_) {
|
| + case TAGGED:
|
| + return Handle<Object>(Memory::Object_at(addr_));
|
| +
|
| + case INT32: {
|
| + int value = Memory::int32_at(addr_);
|
| + if (Smi::IsValid(value)) {
|
| + return Handle<Object>(Smi::FromInt(value));
|
| + } else {
|
| + return Isolate::Current()->factory()->NewNumberFromInt(value);
|
| + }
|
| + }
|
| +
|
| + case DOUBLE: {
|
| + double value = Memory::double_at(addr_);
|
| + return Isolate::Current()->factory()->NewNumber(value);
|
| + }
|
| +
|
| + case LITERAL:
|
| + return literal_;
|
| +
|
| + default:
|
| + UNREACHABLE();
|
| + return Handle<Object>::null();
|
| + }
|
| + }
|
| +
|
| + private:
|
| + Address addr_;
|
| + Handle<Object> literal_;
|
| + SlotRepresentation representation_;
|
| +};
|
| +
|
| +
|
| +static SlotRef ComputeSlotForNextArgument(TranslationIterator* iterator,
|
| + DeoptimizationInputData* data,
|
| + JavaScriptFrame* frame) {
|
| + Translation::Opcode opcode =
|
| + static_cast<Translation::Opcode>(iterator->Next());
|
| +
|
| + switch (opcode) {
|
| + case Translation::BEGIN:
|
| + case Translation::FRAME:
|
| + // Peeled off before getting here.
|
| + break;
|
| +
|
| + case Translation::ARGUMENTS_OBJECT:
|
| + // This can be only emitted for local slots not for argument slots.
|
| + break;
|
| +
|
| + case Translation::REGISTER:
|
| + case Translation::INT32_REGISTER:
|
| + case Translation::DOUBLE_REGISTER:
|
| + case Translation::DUPLICATE:
|
| + // We are at safepoint which corresponds to call. All registers are
|
| + // saved by caller so there would be no live registers at this
|
| + // point. Thus these translation commands should not be used.
|
| + break;
|
| +
|
| + case Translation::STACK_SLOT: {
|
| + int slot_index = iterator->Next();
|
| + Address slot_addr = SlotAddress(frame, slot_index);
|
| + return SlotRef(slot_addr, SlotRef::TAGGED);
|
| + }
|
| +
|
| + case Translation::INT32_STACK_SLOT: {
|
| + int slot_index = iterator->Next();
|
| + Address slot_addr = SlotAddress(frame, slot_index);
|
| + return SlotRef(slot_addr, SlotRef::INT32);
|
| + }
|
| +
|
| + case Translation::DOUBLE_STACK_SLOT: {
|
| + int slot_index = iterator->Next();
|
| + Address slot_addr = SlotAddress(frame, slot_index);
|
| + return SlotRef(slot_addr, SlotRef::DOUBLE);
|
| + }
|
| +
|
| + case Translation::LITERAL: {
|
| + int literal_index = iterator->Next();
|
| + return SlotRef(data->LiteralArray()->get(literal_index));
|
| + }
|
| + }
|
| +
|
| + UNREACHABLE();
|
| + return SlotRef();
|
| +}
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +static void ComputeSlotMappingForArguments(JavaScriptFrame* frame,
|
| + int inlined_frame_index,
|
| + Vector<SlotRef>* args_slots) {
|
| + AssertNoAllocation no_gc;
|
| + int deopt_index = AstNode::kNoNumber;
|
| + DeoptimizationInputData* data =
|
| + static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
|
| + TranslationIterator it(data->TranslationByteArray(),
|
| + data->TranslationIndex(deopt_index)->value());
|
| + Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
|
| + ASSERT(opcode == Translation::BEGIN);
|
| + int frame_count = it.Next();
|
| + USE(frame_count);
|
| + ASSERT(frame_count > inlined_frame_index);
|
| + int frames_to_skip = inlined_frame_index;
|
| + while (true) {
|
| + opcode = static_cast<Translation::Opcode>(it.Next());
|
| + // Skip over operands to advance to the next opcode.
|
| + it.Skip(Translation::NumberOfOperandsFor(opcode));
|
| + if (opcode == Translation::FRAME) {
|
| + if (frames_to_skip == 0) {
|
| + // We reached the frame corresponding to the inlined function
|
| + // in question. Process the translation commands for the
|
| + // arguments.
|
| + //
|
| + // Skip the translation command for the receiver.
|
| + it.Skip(Translation::NumberOfOperandsFor(
|
| + static_cast<Translation::Opcode>(it.Next())));
|
| + // Compute slots for arguments.
|
| + for (int i = 0; i < args_slots->length(); ++i) {
|
| + (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame);
|
| + }
|
| + return;
|
| + }
|
| + frames_to_skip--;
|
| + }
|
| + }
|
| +
|
| + UNREACHABLE();
|
| +}
|
| +
|
|
|
| static MaybeObject* ConstructArgumentsObjectForInlinedFunction(
|
| JavaScriptFrame* frame,
|
| @@ -577,9 +743,7 @@ static MaybeObject* ConstructArgumentsObjectForInlinedFunction(
|
| Factory* factory = Isolate::Current()->factory();
|
| int args_count = inlined_function->shared()->formal_parameter_count();
|
| ScopedVector<SlotRef> args_slots(args_count);
|
| - SlotRef::ComputeSlotMappingForArguments(frame,
|
| - inlined_frame_index,
|
| - &args_slots);
|
| + ComputeSlotMappingForArguments(frame, inlined_frame_index, &args_slots);
|
| Handle<JSObject> arguments =
|
| factory->NewArgumentsObject(inlined_function, args_count);
|
| Handle<FixedArray> array = factory->NewFixedArray(args_count);
|
|
|