Try to preallocate the scratch registers used for inlined keyed loads

to allow fast entry to the deferred code if possible.

Review URL: http://codereview.chromium.org/113457

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1968 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2009-05-15 12:43:00 +00:00
parent 33debd1460
commit dc9473d817
3 changed files with 43 additions and 14 deletions

View File

@ -43,6 +43,16 @@ void DeferredCode::SetEntryFrame(Result* arg) {
}
void DeferredCode::SetEntryFrame(Result* arg0, Result* arg1) {
ASSERT(generator()->has_valid_frame());
generator()->frame()->Push(arg0);
generator()->frame()->Push(arg1);
enter()->set_entry_frame(new VirtualFrame(generator()->frame()));
*arg1 = generator()->frame()->Pop();
*arg0 = generator()->frame()->Pop();
}
// -----------------------------------------------------------------------------
// Support for "structured" code comments.
//

View File

@ -148,6 +148,7 @@ class DeferredCode: public ZoneObject {
// results). This is optional, but should be done before branching
// or jumping to the deferred code.
inline void SetEntryFrame(Result* arg);
inline void SetEntryFrame(Result* arg0, Result* arg1);
JumpTarget* enter() { return &enter_; }

View File

@ -5415,24 +5415,30 @@ void Reference::GetValue(TypeofState typeof_state) {
} else {
// Inline the inobject property case.
Comment cmnt(masm, "[ Inlined named property load");
DeferredReferenceGetNamedValue* deferred =
new DeferredReferenceGetNamedValue(cgen_, GetName());
Result receiver = cgen_->frame()->Pop();
receiver.ToRegister();
// Preallocate the value register to ensure that there is no
// spill emitted between the patch site label and the offset in
// the load instruction and that all frames reaching the
// deferred code are identical.
Result value = cgen_->allocator()->Allocate();
ASSERT(value.is_valid());
// Try to preallocate the value register so that all frames
// reaching the deferred code are identical.
Result value = cgen_->allocator()->AllocateWithoutSpilling();
if (value.is_valid()) {
deferred->SetEntryFrame(&receiver);
}
// Check that the receiver is a heap object.
__ test(receiver.reg(), Immediate(kSmiTagMask));
DeferredReferenceGetNamedValue* deferred =
new DeferredReferenceGetNamedValue(cgen_, GetName());
deferred->SetEntryFrame(&receiver);
deferred->enter()->Branch(zero, &receiver, not_taken);
// Do not allocate the value register after binding the patch
// site label. The distance from the patch site to the offset
// must be constant.
if (!value.is_valid()) {
value = cgen_->allocator()->Allocate();
ASSERT(value.is_valid());
}
__ bind(deferred->patch_site());
// This is the map check instruction that will be patched (so we can't
// use the double underscore macro that may insert instructions).
@ -5482,6 +5488,14 @@ void Reference::GetValue(TypeofState typeof_state) {
key.ToRegister();
receiver.ToRegister();
// Try to preallocate the elements and index scratch registers
// so that all frames reaching the deferred code are identical.
Result elements = cgen_->allocator()->AllocateWithoutSpilling();
Result index = cgen_->allocator()->AllocateWithoutSpilling();
if (elements.is_valid() && index.is_valid()) {
deferred->SetEntryFrame(&receiver, &key);
}
// Check that the receiver is not a smi (only needed if this
// is not a load from the global context) and that it has the
// expected map.
@ -5505,8 +5519,10 @@ void Reference::GetValue(TypeofState typeof_state) {
// Get the elements array from the receiver and check that it
// is not a dictionary.
Result elements = cgen_->allocator()->Allocate();
ASSERT(elements.is_valid());
if (!elements.is_valid()) {
elements = cgen_->allocator()->Allocate();
ASSERT(elements.is_valid());
}
__ mov(elements.reg(),
FieldOperand(receiver.reg(), JSObject::kElementsOffset));
__ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset),
@ -5515,8 +5531,10 @@ void Reference::GetValue(TypeofState typeof_state) {
// Shift the key to get the actual index value and check that
// it is within bounds.
Result index = cgen_->allocator()->Allocate();
ASSERT(index.is_valid());
if (!index.is_valid()) {
index = cgen_->allocator()->Allocate();
ASSERT(index.is_valid());
}
__ mov(index.reg(), key.reg());
__ sar(index.reg(), kSmiTagSize);
__ cmp(index.reg(),