Revert dynamic frame alignment (r9415)
Marking aligned frames with a marker can produce false positives since an optimized frame spill slot may be mistakenly seen as a marker value. It also breaks the debugger reproducably: Tested when enabling alignment for all functions and running the debugger unit tests. BUG=v8:2009 TEST=no crashes in EarleyBoyer Review URL: https://chromiumcodereview.appspot.com/9703110 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11075 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
2dc04fda4a
commit
1a29d5cf33
@ -358,8 +358,6 @@ Deoptimizer::Deoptimizer(Isolate* isolate,
|
||||
output_count_(0),
|
||||
jsframe_count_(0),
|
||||
output_(NULL),
|
||||
frame_alignment_marker_(isolate->heap()->frame_alignment_marker()),
|
||||
has_alignment_padding_(0),
|
||||
deferred_heap_numbers_(0) {
|
||||
if (FLAG_trace_deopt && type != OSR) {
|
||||
if (type == DEBUGGER) {
|
||||
|
@ -220,11 +220,6 @@ class Deoptimizer : public Malloced {
|
||||
return OFFSET_OF(Deoptimizer, output_count_);
|
||||
}
|
||||
static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
|
||||
static int frame_alignment_marker_offset() {
|
||||
return OFFSET_OF(Deoptimizer, frame_alignment_marker_); }
|
||||
static int has_alignment_padding_offset() {
|
||||
return OFFSET_OF(Deoptimizer, has_alignment_padding_);
|
||||
}
|
||||
|
||||
static int GetDeoptimizedCodeCount(Isolate* isolate);
|
||||
|
||||
@ -337,10 +332,6 @@ class Deoptimizer : public Malloced {
|
||||
// Array of output frame descriptions.
|
||||
FrameDescription** output_;
|
||||
|
||||
// Frames can be dynamically padded on ia32 to align untagged doubles.
|
||||
Object* frame_alignment_marker_;
|
||||
intptr_t has_alignment_padding_;
|
||||
|
||||
List<HeapNumberMaterializationDescriptor> deferred_heap_numbers_;
|
||||
|
||||
static const int table_entry_size_;
|
||||
|
14
src/heap.cc
14
src/heap.cc
@ -2471,34 +2471,26 @@ bool Heap::CreateInitialObjects() {
|
||||
set_the_hole_value(Oddball::cast(obj));
|
||||
|
||||
{ MaybeObject* maybe_obj = CreateOddball("arguments_marker",
|
||||
Smi::FromInt(-2),
|
||||
Smi::FromInt(-4),
|
||||
Oddball::kArgumentMarker);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
}
|
||||
set_arguments_marker(Oddball::cast(obj));
|
||||
|
||||
{ MaybeObject* maybe_obj = CreateOddball("no_interceptor_result_sentinel",
|
||||
Smi::FromInt(-3),
|
||||
Smi::FromInt(-2),
|
||||
Oddball::kOther);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
}
|
||||
set_no_interceptor_result_sentinel(obj);
|
||||
|
||||
{ MaybeObject* maybe_obj = CreateOddball("termination_exception",
|
||||
Smi::FromInt(-4),
|
||||
Smi::FromInt(-3),
|
||||
Oddball::kOther);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
}
|
||||
set_termination_exception(obj);
|
||||
|
||||
{ MaybeObject* maybe_obj = CreateOddball("frame_alignment_marker",
|
||||
Smi::FromInt(-5),
|
||||
Oddball::kOther);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
}
|
||||
set_frame_alignment_marker(Oddball::cast(obj));
|
||||
STATIC_ASSERT(Oddball::kLeastHiddenOddballNumber == -5);
|
||||
|
||||
// Allocate the empty string.
|
||||
{ MaybeObject* maybe_obj = AllocateRawAsciiString(0, TENURED);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
|
@ -77,7 +77,6 @@ namespace internal {
|
||||
V(String, empty_string, EmptyString) \
|
||||
V(DescriptorArray, empty_descriptor_array, EmptyDescriptorArray) \
|
||||
V(Smi, stack_limit, StackLimit) \
|
||||
V(Oddball, frame_alignment_marker, FrameAlignmentMarker) \
|
||||
V(Oddball, arguments_marker, ArgumentsMarker) \
|
||||
/* The first 32 roots above this line should be boring from a GC point of */ \
|
||||
/* view. This means they are never in new space and never on a page that */ \
|
||||
|
@ -427,14 +427,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
|
||||
output_[0]->SetPc(reinterpret_cast<uint32_t>(from_));
|
||||
} else {
|
||||
// Set up the frame pointer and the context pointer.
|
||||
// All OSR stack frames are dynamically aligned to an 8-byte boundary.
|
||||
int frame_pointer = input_->GetRegister(ebp.code());
|
||||
if ((frame_pointer & 0x4) == 0) {
|
||||
// Return address at FP + 4 should be aligned, so FP mod 8 should be 4.
|
||||
frame_pointer -= kPointerSize;
|
||||
has_alignment_padding_ = 1;
|
||||
}
|
||||
output_[0]->SetRegister(ebp.code(), frame_pointer);
|
||||
output_[0]->SetRegister(ebp.code(), input_->GetRegister(ebp.code()));
|
||||
output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code()));
|
||||
|
||||
unsigned pc_offset = data->OsrPcOffset()->value();
|
||||
@ -692,11 +685,9 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||
// top address and the current frame's size.
|
||||
uint32_t top_address;
|
||||
if (is_bottommost) {
|
||||
// If the optimized frame had alignment padding, adjust the frame pointer
|
||||
// to point to the new position of the old frame pointer after padding
|
||||
// is removed. Subtract 2 * kPointerSize for the context and function slots.
|
||||
top_address = input_->GetRegister(ebp.code()) - (2 * kPointerSize) -
|
||||
height_in_bytes + has_alignment_padding_ * kPointerSize;
|
||||
// 2 = context and function in the frame.
|
||||
top_address =
|
||||
input_->GetRegister(ebp.code()) - (2 * kPointerSize) - height_in_bytes;
|
||||
} else {
|
||||
top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
}
|
||||
@ -747,9 +738,7 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||
}
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
ASSERT(!is_bottommost ||
|
||||
input_->GetRegister(ebp.code()) + has_alignment_padding_ * kPointerSize
|
||||
== fp_value);
|
||||
ASSERT(!is_bottommost || input_->GetRegister(ebp.code()) == fp_value);
|
||||
output_frame->SetFp(fp_value);
|
||||
if (is_topmost) output_frame->SetRegister(ebp.code(), fp_value);
|
||||
if (FLAG_trace_deopt) {
|
||||
@ -939,17 +928,6 @@ void Deoptimizer::EntryGenerator::Generate() {
|
||||
__ cmp(ecx, esp);
|
||||
__ j(not_equal, &pop_loop);
|
||||
|
||||
// If frame was dynamically aligned, pop padding.
|
||||
Label sentinel, sentinel_done;
|
||||
__ pop(ecx);
|
||||
__ cmp(ecx, Operand(eax, Deoptimizer::frame_alignment_marker_offset()));
|
||||
__ j(equal, &sentinel);
|
||||
__ push(ecx);
|
||||
__ jmp(&sentinel_done);
|
||||
__ bind(&sentinel);
|
||||
__ mov(Operand(eax, Deoptimizer::has_alignment_padding_offset()),
|
||||
Immediate(1));
|
||||
__ bind(&sentinel_done);
|
||||
// Compute the output frame in the deoptimizer.
|
||||
__ push(eax);
|
||||
__ PrepareCallCFunction(1, ebx);
|
||||
@ -961,17 +939,6 @@ void Deoptimizer::EntryGenerator::Generate() {
|
||||
}
|
||||
__ pop(eax);
|
||||
|
||||
if (type() == OSR) {
|
||||
// If alignment padding is added, push the sentinel.
|
||||
Label no_osr_padding;
|
||||
__ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()),
|
||||
Immediate(0));
|
||||
__ j(equal, &no_osr_padding, Label::kNear);
|
||||
__ push(Operand(eax, Deoptimizer::frame_alignment_marker_offset()));
|
||||
__ bind(&no_osr_padding);
|
||||
}
|
||||
|
||||
|
||||
// Replace the current frame with the output frames.
|
||||
Label outer_push_loop, inner_push_loop;
|
||||
// Outer loop state: eax = current FrameDescription**, edx = one past the
|
||||
|
@ -79,9 +79,6 @@ bool LCodeGen::GenerateCode() {
|
||||
// the frame (that is done in GeneratePrologue).
|
||||
FrameScope frame_scope(masm_, StackFrame::MANUAL);
|
||||
|
||||
dynamic_frame_alignment_ = chunk()->num_double_slots() > 2 ||
|
||||
info()->osr_ast_id() != AstNode::kNoNumber;
|
||||
|
||||
return GeneratePrologue() &&
|
||||
GenerateBody() &&
|
||||
GenerateDeferredCode() &&
|
||||
@ -156,29 +153,6 @@ bool LCodeGen::GeneratePrologue() {
|
||||
__ bind(&ok);
|
||||
}
|
||||
|
||||
if (dynamic_frame_alignment_) {
|
||||
Label do_not_pad, align_loop;
|
||||
STATIC_ASSERT(kDoubleSize == 2 * kPointerSize);
|
||||
// Align esp to a multiple of 2 * kPointerSize.
|
||||
__ test(esp, Immediate(kPointerSize));
|
||||
__ j(zero, &do_not_pad, Label::kNear);
|
||||
__ push(Immediate(0));
|
||||
__ mov(ebx, esp);
|
||||
// Copy arguments, receiver, and return address.
|
||||
__ mov(ecx, Immediate(scope()->num_parameters() + 2));
|
||||
|
||||
__ bind(&align_loop);
|
||||
__ mov(eax, Operand(ebx, 1 * kPointerSize));
|
||||
__ mov(Operand(ebx, 0), eax);
|
||||
__ add(Operand(ebx), Immediate(kPointerSize));
|
||||
__ dec(ecx);
|
||||
__ j(not_zero, &align_loop, Label::kNear);
|
||||
__ mov(Operand(ebx, 0),
|
||||
Immediate(isolate()->factory()->frame_alignment_marker()));
|
||||
|
||||
__ bind(&do_not_pad);
|
||||
}
|
||||
|
||||
__ push(ebp); // Caller's frame pointer.
|
||||
__ mov(ebp, esp);
|
||||
__ push(esi); // Callee's context.
|
||||
@ -2125,17 +2099,6 @@ void LCodeGen::DoReturn(LReturn* instr) {
|
||||
}
|
||||
__ mov(esp, ebp);
|
||||
__ pop(ebp);
|
||||
if (dynamic_frame_alignment_) {
|
||||
Label aligned;
|
||||
// Frame alignment marker (padding) is below arguments,
|
||||
// and receiver, so its return-address-relative offset is
|
||||
// (num_arguments + 2) words.
|
||||
__ cmp(Operand(esp, (GetParameterCount() + 2) * kPointerSize),
|
||||
Immediate(factory()->frame_alignment_marker()));
|
||||
__ j(not_equal, &aligned);
|
||||
__ Ret((GetParameterCount() + 2) * kPointerSize, ecx);
|
||||
__ bind(&aligned);
|
||||
}
|
||||
__ Ret((GetParameterCount() + 1) * kPointerSize, ecx);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,6 @@ class LCodeGen BASE_EMBEDDED {
|
||||
inlined_function_count_(0),
|
||||
scope_(info->scope()),
|
||||
status_(UNUSED),
|
||||
dynamic_frame_alignment_(false),
|
||||
deferred_(8),
|
||||
osr_pc_offset_(-1),
|
||||
last_lazy_deopt_pc_(0),
|
||||
@ -145,10 +144,6 @@ class LCodeGen BASE_EMBEDDED {
|
||||
StrictModeFlag strict_mode_flag() const {
|
||||
return info()->is_classic_mode() ? kNonStrictMode : kStrictMode;
|
||||
}
|
||||
bool dynamic_frame_alignment() const { return dynamic_frame_alignment_; }
|
||||
void set_dynamic_frame_alignment(bool value) {
|
||||
dynamic_frame_alignment_ = value;
|
||||
}
|
||||
|
||||
LChunk* chunk() const { return chunk_; }
|
||||
Scope* scope() const { return scope_; }
|
||||
@ -333,7 +328,6 @@ class LCodeGen BASE_EMBEDDED {
|
||||
int inlined_function_count_;
|
||||
Scope* const scope_;
|
||||
Status status_;
|
||||
bool dynamic_frame_alignment_;
|
||||
TranslationBuffer translations_;
|
||||
ZoneList<LDeferredCode*> deferred_;
|
||||
int osr_pc_offset_;
|
||||
|
@ -368,11 +368,7 @@ void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
|
||||
|
||||
int LChunk::GetNextSpillIndex(bool is_double) {
|
||||
// Skip a slot if for a double-width slot.
|
||||
if (is_double) {
|
||||
spill_slot_count_ |= 1; // Make it odd, so incrementing makes it even.
|
||||
spill_slot_count_++;
|
||||
num_double_slots_++;
|
||||
}
|
||||
if (is_double) spill_slot_count_++;
|
||||
return spill_slot_count_++;
|
||||
}
|
||||
|
||||
|
@ -2289,7 +2289,6 @@ class LChunk: public ZoneObject {
|
||||
graph_(graph),
|
||||
instructions_(32),
|
||||
pointer_maps_(8),
|
||||
num_double_slots_(0),
|
||||
inlined_closures_(1) { }
|
||||
|
||||
void AddInstruction(LInstruction* instruction, HBasicBlock* block);
|
||||
@ -2303,8 +2302,6 @@ class LChunk: public ZoneObject {
|
||||
int ParameterAt(int index);
|
||||
int GetParameterStackSlot(int index) const;
|
||||
int spill_slot_count() const { return spill_slot_count_; }
|
||||
int num_double_slots() const { return num_double_slots_; }
|
||||
|
||||
CompilationInfo* info() const { return info_; }
|
||||
HGraph* graph() const { return graph_; }
|
||||
const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
|
||||
@ -2346,7 +2343,6 @@ class LChunk: public ZoneObject {
|
||||
HGraph* const graph_;
|
||||
ZoneList<LInstruction*> instructions_;
|
||||
ZoneList<LPointerMap*> pointer_maps_;
|
||||
int num_double_slots_;
|
||||
ZoneList<Handle<JSFunction> > inlined_closures_;
|
||||
};
|
||||
|
||||
|
@ -532,8 +532,9 @@ void Oddball::OddballVerify() {
|
||||
} else {
|
||||
ASSERT(number->IsSmi());
|
||||
int value = Smi::cast(number)->value();
|
||||
ASSERT(value <= 1);
|
||||
// Hidden oddballs have negative smis.
|
||||
const int kLeastHiddenOddballNumber = -4;
|
||||
ASSERT(value <= 1);
|
||||
ASSERT(value >= kLeastHiddenOddballNumber);
|
||||
}
|
||||
}
|
||||
|
@ -7581,9 +7581,6 @@ class Oddball: public HeapObject {
|
||||
static const byte kUndefined = 5;
|
||||
static const byte kOther = 6;
|
||||
|
||||
// The ToNumber value of a hidden oddball is a negative smi.
|
||||
static const int kLeastHiddenOddballNumber = -5;
|
||||
|
||||
typedef FixedBodyDescriptor<kToStringOffset,
|
||||
kToNumberOffset + kPointerSize,
|
||||
kSize> BodyDescriptor;
|
||||
|
Loading…
Reference in New Issue
Block a user