Commit 0b4c1efd authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Improve the success rate for inline keyed store on x64

Added a simple new space check on the elements fixed array which can allow
updating with other values than smis without updating the remembered set.

Also combined the positive smi and range check so that a separate smi check can be avoided when the key is known to be a smi.

This is a port of r4543.
Review URL: http://codereview.chromium.org/1702013

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4547 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0aa67676
...@@ -100,6 +100,7 @@ void MacroAssembler::InNewSpace(Register object, ...@@ -100,6 +100,7 @@ void MacroAssembler::InNewSpace(Register object,
Register scratch, Register scratch,
Condition cc, Condition cc,
Label* branch) { Label* branch) {
ASSERT(cc == equal || cc == not_equal);
if (Serializer::enabled()) { if (Serializer::enabled()) {
// Can't do arithmetic on external references if it might get serialized. // Can't do arithmetic on external references if it might get serialized.
mov(scratch, Operand(object)); mov(scratch, Operand(object));
......
...@@ -6997,6 +6997,8 @@ void Reference::SetValue(InitState init_state) { ...@@ -6997,6 +6997,8 @@ void Reference::SetValue(InitState init_state) {
Result tmp = cgen_->allocator_->Allocate(); Result tmp = cgen_->allocator_->Allocate();
ASSERT(tmp.is_valid()); ASSERT(tmp.is_valid());
Result tmp2 = cgen_->allocator_->Allocate();
ASSERT(tmp2.is_valid());
// Determine whether the value is a constant before putting it // Determine whether the value is a constant before putting it
// in a register. // in a register.
...@@ -7012,32 +7014,44 @@ void Reference::SetValue(InitState init_state) { ...@@ -7012,32 +7014,44 @@ void Reference::SetValue(InitState init_state) {
key.reg(), key.reg(),
receiver.reg()); receiver.reg());
// Check that the value is a smi if it is not a constant.
// We can skip the write barrier for smis and constants.
if (!value_is_constant) {
__ JumpIfNotSmi(value.reg(), deferred->entry_label());
}
// Check that the key is a non-negative smi.
__ JumpIfNotPositiveSmi(key.reg(), deferred->entry_label());
// Check that the receiver is not a smi. // Check that the receiver is not a smi.
__ JumpIfSmi(receiver.reg(), deferred->entry_label()); __ JumpIfSmi(receiver.reg(), deferred->entry_label());
// Check that the key is a smi.
if (!key.is_smi()) {
__ JumpIfNotSmi(key.reg(), deferred->entry_label());
} else {
if (FLAG_debug_code) {
__ AbortIfNotSmi(key.reg(), "Non-smi value in smi-typed value.");
}
}
// Check that the receiver is a JSArray. // Check that the receiver is a JSArray.
__ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister); __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister);
deferred->Branch(not_equal); deferred->Branch(not_equal);
// Check that the key is within bounds. Both the key and the // Check that the key is within bounds. Both the key and the
// length of the JSArray are smis. // length of the JSArray are smis. Use unsigned comparison to handle
// negative keys.
__ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset), __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset),
key.reg()); key.reg());
deferred->Branch(less_equal); deferred->Branch(below_equal);
// Get the elements array from the receiver and check that it // Get the elements array from the receiver and check that it
// is a flat array (not a dictionary). // is a flat array (not a dictionary).
__ movq(tmp.reg(), __ movq(tmp.reg(),
FieldOperand(receiver.reg(), JSObject::kElementsOffset)); FieldOperand(receiver.reg(), JSObject::kElementsOffset));
// Check whether it is possible to omit the write barrier. If the
// elements array is in new space or the value written is a smi we can
// safely update the elements array without updating the remembered set.
Label in_new_space;
__ InNewSpace(tmp.reg(), tmp2.reg(), equal, &in_new_space);
if (!value_is_constant) {
__ JumpIfNotSmi(value.reg(), deferred->entry_label());
}
__ bind(&in_new_space);
// Bind the deferred code patch site to be able to locate the // Bind the deferred code patch site to be able to locate the
// fixed array map comparison. When debugging, we patch this // fixed array map comparison. When debugging, we patch this
// comparison to always fail so that we will hit the IC call // comparison to always fail so that we will hit the IC call
......
...@@ -167,6 +167,22 @@ void RecordWriteStub::Generate(MacroAssembler* masm) { ...@@ -167,6 +167,22 @@ void RecordWriteStub::Generate(MacroAssembler* masm) {
} }
void MacroAssembler::InNewSpace(Register object,
Register scratch,
Condition cc,
Label* branch) {
ASSERT(cc == equal || cc == not_equal);
if (!scratch.is(object)) {
movq(scratch, object);
}
ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask())));
and_(scratch, Immediate(static_cast<int32_t>(Heap::NewSpaceMask())));
movq(kScratchRegister, ExternalReference::new_space_start());
cmpq(scratch, kScratchRegister);
j(cc, branch);
}
// Set the remembered set bit for [object+offset]. // Set the remembered set bit for [object+offset].
// object is the object being stored into, value is the object being stored. // object is the object being stored into, value is the object being stored.
// If offset is zero, then the smi_index register contains the array index into // If offset is zero, then the smi_index register contains the array index into
...@@ -219,12 +235,7 @@ void MacroAssembler::RecordWriteNonSmi(Register object, ...@@ -219,12 +235,7 @@ void MacroAssembler::RecordWriteNonSmi(Register object,
// Test that the object address is not in the new space. We cannot // Test that the object address is not in the new space. We cannot
// set remembered set bits in the new space. // set remembered set bits in the new space.
movq(scratch, object); InNewSpace(object, scratch, equal, &done);
ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask())));
and_(scratch, Immediate(static_cast<int32_t>(Heap::NewSpaceMask())));
movq(kScratchRegister, ExternalReference::new_space_start());
cmpq(scratch, kScratchRegister);
j(equal, &done);
// The offset is relative to a tagged or untagged HeapObject pointer, // The offset is relative to a tagged or untagged HeapObject pointer,
// so either offset or offset + kHeapObjectTag must be a // so either offset or offset + kHeapObjectTag must be a
......
...@@ -66,6 +66,14 @@ class MacroAssembler: public Assembler { ...@@ -66,6 +66,14 @@ class MacroAssembler: public Assembler {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// GC Support // GC Support
// Check if object is in new space. The condition cc can be equal or
// not_equal. If it is equal a jump will be done if the object is on new
// space. The register scratch can be object itself, but it will be clobbered.
void InNewSpace(Register object,
Register scratch,
Condition cc,
Label* branch);
// Set the remembered set bit for [object+offset]. // Set the remembered set bit for [object+offset].
// object is the object being stored into, value is the object being stored. // object is the object being stored into, value is the object being stored.
// If offset is zero, then the scratch register contains the array index into // If offset is zero, then the scratch register contains the array index into
......
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