Commit 8d96a019 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Fix deserializer to understand direct pointers from code to cell payloads.

The deoptimizer generates full-code-generator code and relies on it having
the same layout as last time.  This means that the code the full code
generator makes for the snapshot should be the same as the code it makes
later.  This change makes the full code generator create more consistent
code between mksnapshot time and run time.

This is a bug fix and a step towards making the snapshot code more robust.
Review URL: https://chromiumcodereview.appspot.com/10824084

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12233 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9641c255
......@@ -141,10 +141,7 @@ Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
JSGlobalPropertyCell* RelocInfo::target_cell() {
ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
Address address = Memory::Address_at(pc_);
Object* object = HeapObject::FromAddress(
address - JSGlobalPropertyCell::kValueOffset);
return reinterpret_cast<JSGlobalPropertyCell*>(object);
return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
}
......
......@@ -2364,16 +2364,14 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
// Record source position for debugger.
SetSourcePosition(expr->position());
// Record call targets in unoptimized code, but not in the snapshot.
if (!Serializer::enabled()) {
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ mov(r2, Operand(cell));
}
// Record call targets in unoptimized code.
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ mov(r2, Operand(cell));
CallFunctionStub stub(arg_count, flags);
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
......@@ -2563,21 +2561,15 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
__ mov(r0, Operand(arg_count));
__ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
// Record call targets in unoptimized code, but not in the snapshot.
CallFunctionFlags flags;
if (!Serializer::enabled()) {
flags = RECORD_CALL_TARGET;
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ mov(r2, Operand(cell));
} else {
flags = NO_CALL_FUNCTION_FLAGS;
}
// Record call targets in unoptimized code.
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ mov(r2, Operand(cell));
CallConstructStub stub(flags);
CallConstructStub stub(RECORD_CALL_TARGET);
__ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
context()->Plug(r0);
......
......@@ -1267,12 +1267,12 @@ void Heap::Scavenge() {
// Copy objects reachable from cells by scavenging cell values directly.
HeapObjectIterator cell_iterator(cell_space_);
for (HeapObject* cell = cell_iterator.Next();
cell != NULL; cell = cell_iterator.Next()) {
if (cell->IsJSGlobalPropertyCell()) {
Address value_address =
reinterpret_cast<Address>(cell) +
(JSGlobalPropertyCell::kValueOffset - kHeapObjectTag);
for (HeapObject* heap_object = cell_iterator.Next();
heap_object != NULL;
heap_object = cell_iterator.Next()) {
if (heap_object->IsJSGlobalPropertyCell()) {
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(heap_object);
Address value_address = cell->ValueAddress();
scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
}
}
......
......@@ -150,10 +150,7 @@ Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
JSGlobalPropertyCell* RelocInfo::target_cell() {
ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
Address address = Memory::Address_at(pc_);
Object* object = HeapObject::FromAddress(
address - JSGlobalPropertyCell::kValueOffset);
return reinterpret_cast<JSGlobalPropertyCell*>(object);
return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
}
......
......@@ -2305,16 +2305,14 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
// Record source position for debugger.
SetSourcePosition(expr->position());
// Record call targets in unoptimized code, but not in the snapshot.
if (!Serializer::enabled()) {
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ mov(ebx, cell);
}
// Record call targets in unoptimized code.
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ mov(ebx, cell);
CallFunctionStub stub(arg_count, flags);
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
......@@ -2493,21 +2491,15 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
__ Set(eax, Immediate(arg_count));
__ mov(edi, Operand(esp, arg_count * kPointerSize));
// Record call targets in unoptimized code, but not in the snapshot.
CallFunctionFlags flags;
if (!Serializer::enabled()) {
flags = RECORD_CALL_TARGET;
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ mov(ebx, cell);
} else {
flags = NO_CALL_FUNCTION_FLAGS;
}
// Record call targets in unoptimized code.
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ mov(ebx, cell);
CallConstructStub stub(flags);
CallConstructStub stub(RECORD_CALL_TARGET);
__ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
context()->Plug(eax);
......
......@@ -208,10 +208,7 @@ Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
JSGlobalPropertyCell* RelocInfo::target_cell() {
ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
Address address = Memory::Address_at(pc_);
Object* object = HeapObject::FromAddress(
address - JSGlobalPropertyCell::kValueOffset);
return reinterpret_cast<JSGlobalPropertyCell*>(object);
return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
}
......
......@@ -2389,16 +2389,14 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
// Record source position for debugger.
SetSourcePosition(expr->position());
// Record call targets in unoptimized code, but not in the snapshot.
if (!Serializer::enabled()) {
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ li(a2, Operand(cell));
}
// Record call targets.
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ li(a2, Operand(cell));
CallFunctionStub stub(arg_count, flags);
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
......@@ -2587,21 +2585,15 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
__ li(a0, Operand(arg_count));
__ lw(a1, MemOperand(sp, arg_count * kPointerSize));
// Record call targets in unoptimized code, but not in the snapshot.
CallFunctionFlags flags;
if (!Serializer::enabled()) {
flags = RECORD_CALL_TARGET;
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ li(a2, Operand(cell));
} else {
flags = NO_CALL_FUNCTION_FLAGS;
}
// Record call targets in unoptimized code.
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ li(a2, Operand(cell));
CallConstructStub stub(flags);
CallConstructStub stub(RECORD_CALL_TARGET);
__ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
context()->Plug(v0);
......
......@@ -7927,6 +7927,14 @@ class JSGlobalPropertyCell: public HeapObject {
// Casting.
static inline JSGlobalPropertyCell* cast(Object* obj);
static inline JSGlobalPropertyCell* FromValueAddress(Address value) {
return cast(FromAddress(value - kValueOffset));
}
inline Address ValueAddress() {
return address() + kValueOffset;
}
#ifdef DEBUG
void JSGlobalPropertyCellVerify();
#endif
......
......@@ -838,10 +838,18 @@ void Deserializer::ReadChunk(Object** current,
new_object = HeapObject::FromAddress(object_address); \
} \
} \
if (within == kFirstInstruction) { \
Code* new_code_object = reinterpret_cast<Code*>(new_object); \
new_object = reinterpret_cast<Object*>( \
new_code_object->instruction_start()); \
if (within == kInnerPointer) { \
if (space_number != CODE_SPACE || new_object->IsCode()) { \
Code* new_code_object = reinterpret_cast<Code*>(new_object); \
new_object = reinterpret_cast<Object*>( \
new_code_object->instruction_start()); \
} else { \
ASSERT(space_number == CODE_SPACE || space_number == kLargeCode);\
JSGlobalPropertyCell* cell = \
JSGlobalPropertyCell::cast(new_object); \
new_object = reinterpret_cast<Object*>( \
cell->ValueAddress()); \
} \
} \
if (how == kFromCode) { \
Address location_of_branch_data = \
......@@ -979,11 +987,13 @@ void Deserializer::ReadChunk(Object** current,
// Deserialize a new object and write a pointer to it to the current
// object.
ONE_PER_SPACE(kNewObject, kPlain, kStartOfObject)
// Support for direct instruction pointers in functions
ONE_PER_CODE_SPACE(kNewObject, kPlain, kFirstInstruction)
// Support for direct instruction pointers in functions. It's an inner
// pointer because it points at the entry point, not at the start of the
// code object.
ONE_PER_CODE_SPACE(kNewObject, kPlain, kInnerPointer)
// Deserialize a new code object and write a pointer to its first
// instruction to the current code object.
ONE_PER_SPACE(kNewObject, kFromCode, kFirstInstruction)
ONE_PER_SPACE(kNewObject, kFromCode, kInnerPointer)
// Find a recently deserialized object using its offset from the current
// allocation point and write a pointer to it to the current object.
ALL_SPACES(kBackref, kPlain, kStartOfObject)
......@@ -1006,16 +1016,16 @@ void Deserializer::ReadChunk(Object** current,
// current allocation point and write a pointer to its first instruction
// to the current code object or the instruction pointer in a function
// object.
ALL_SPACES(kBackref, kFromCode, kFirstInstruction)
ALL_SPACES(kBackref, kPlain, kFirstInstruction)
ALL_SPACES(kBackref, kFromCode, kInnerPointer)
ALL_SPACES(kBackref, kPlain, kInnerPointer)
// Find an already deserialized object using its offset from the start
// and write a pointer to it to the current object.
ALL_SPACES(kFromStart, kPlain, kStartOfObject)
ALL_SPACES(kFromStart, kPlain, kFirstInstruction)
ALL_SPACES(kFromStart, kPlain, kInnerPointer)
// Find an already deserialized code object using its offset from the
// start and write a pointer to its first instruction to the current code
// object.
ALL_SPACES(kFromStart, kFromCode, kFirstInstruction)
ALL_SPACES(kFromStart, kFromCode, kInnerPointer)
// Find an object in the roots array and write a pointer to it to the
// current object.
CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0)
......@@ -1030,10 +1040,10 @@ void Deserializer::ReadChunk(Object** current,
kUnknownOffsetFromStart)
// Find an code entry in the partial snapshots cache and
// write a pointer to it to the current object.
CASE_STATEMENT(kPartialSnapshotCache, kPlain, kFirstInstruction, 0)
CASE_STATEMENT(kPartialSnapshotCache, kPlain, kInnerPointer, 0)
CASE_BODY(kPartialSnapshotCache,
kPlain,
kFirstInstruction,
kInnerPointer,
0,
kUnknownOffsetFromStart)
// Find an external reference and write a pointer to it to the current
......@@ -1540,7 +1550,7 @@ void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
Address target_start = rinfo->target_address_address();
OutputRawData(target_start);
Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
serializer_->SerializeObject(target, kFromCode, kFirstInstruction);
serializer_->SerializeObject(target, kFromCode, kInnerPointer);
bytes_processed_so_far_ += rinfo->target_address_size();
}
......@@ -1548,15 +1558,17 @@ void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
void Serializer::ObjectSerializer::VisitCodeEntry(Address entry_address) {
Code* target = Code::cast(Code::GetObjectFromEntryAddress(entry_address));
OutputRawData(entry_address);
serializer_->SerializeObject(target, kPlain, kFirstInstruction);
serializer_->SerializeObject(target, kPlain, kInnerPointer);
bytes_processed_so_far_ += kPointerSize;
}
void Serializer::ObjectSerializer::VisitGlobalPropertyCell(RelocInfo* rinfo) {
// We shouldn't have any global property cell references in code
// objects in the snapshot.
UNREACHABLE();
ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
JSGlobalPropertyCell* cell =
JSGlobalPropertyCell::cast(rinfo->target_cell());
OutputRawData(rinfo->pc());
serializer_->SerializeObject(cell, kPlain, kInnerPointer);
}
......
......@@ -242,7 +242,7 @@ class SerializerDeserializer: public ObjectVisitor {
// Where to point within the object.
enum WhereToPoint {
kStartOfObject = 0,
kFirstInstruction = 0x80,
kInnerPointer = 0x80, // First insn in code object or payload of cell.
kWhereToPointMask = 0x80
};
......
......@@ -309,10 +309,7 @@ Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
JSGlobalPropertyCell* RelocInfo::target_cell() {
ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
Address address = Memory::Address_at(pc_);
Object* object = HeapObject::FromAddress(
address - JSGlobalPropertyCell::kValueOffset);
return reinterpret_cast<JSGlobalPropertyCell*>(object);
return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
}
......
......@@ -2278,16 +2278,14 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
// Record source position for debugger.
SetSourcePosition(expr->position());
// Record call targets in unoptimized code, but not in the snapshot.
if (!Serializer::enabled()) {
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ Move(rbx, cell);
}
// Record call targets in unoptimized code.
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ Move(rbx, cell);
CallFunctionStub stub(arg_count, flags);
__ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
......@@ -2466,20 +2464,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
__ movq(rdi, Operand(rsp, arg_count * kPointerSize));
// Record call targets in unoptimized code, but not in the snapshot.
CallFunctionFlags flags;
if (!Serializer::enabled()) {
flags = RECORD_CALL_TARGET;
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ Move(rbx, cell);
} else {
flags = NO_CALL_FUNCTION_FLAGS;
}
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
RecordTypeFeedbackCell(expr->id(), cell);
__ Move(rbx, cell);
CallConstructStub stub(flags);
CallConstructStub stub(RECORD_CALL_TARGET);
__ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
context()->Plug(rax);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment