X64: Add StoreField inline cache stub.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2518 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2009-07-22 09:11:33 +00:00
parent a109c08c78
commit be562ee794
2 changed files with 110 additions and 7 deletions

View File

@ -212,7 +212,8 @@ class MacroAssembler: public Assembler {
// Generate code for checking access rights - used for security checks // Generate code for checking access rights - used for security checks
// on access to global objects across environments. The holder register // on access to global objects across environments. The holder register
// is left untouched, but the scratch register is clobbered. // is left untouched, but the scratch register and kScratchRegister,
// which must be different, are clobbered.
void CheckAccessGlobalProxy(Register holder_reg, void CheckAccessGlobalProxy(Register holder_reg,
Register scratch, Register scratch,
Label* miss); Label* miss);

View File

@ -427,12 +427,38 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* a,
} }
Object* StoreStubCompiler::CompileStoreField(JSObject* a, Object* StoreStubCompiler::CompileStoreField(JSObject* object,
int b, int index,
Map* c, Map* transition,
String* d) { String* name) {
UNIMPLEMENTED(); // ----------- S t a t e -------------
return NULL; // -- rax : value
// -- rcx : name
// -- rsp[0] : return address
// -- rsp[8] : receiver
// -----------------------------------
Label miss;
// Get the object from the stack.
__ movq(rbx, Operand(rsp, 1 * kPointerSize));
// Generate store field code. Trashes the name register.
GenerateStoreField(masm(),
Builtins::StoreIC_ExtendStorage,
object,
index,
transition,
rbx, rcx, rdx,
&miss);
// Handle store cache miss.
__ bind(&miss);
__ Move(rcx, Handle<String>(name)); // restore name
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code.
return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
} }
@ -699,6 +725,82 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
} }
void StubCompiler::GenerateStoreField(MacroAssembler* masm,
Builtins::Name storage_extend,
JSObject* object,
int index,
Map* transition,
Register receiver_reg,
Register name_reg,
Register scratch,
Label* miss_label) {
// Check that the object isn't a smi.
__ testl(receiver_reg, Immediate(kSmiTagMask));
__ j(zero, miss_label);
// Check that the map of the object hasn't changed.
__ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
Handle<Map>(object->map()));
__ j(not_equal, miss_label);
// Perform global security token check if needed.
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
}
// Stub never generated for non-global objects that require access
// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
// Perform map transition for the receiver if necessary.
if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array.
__ Move(rcx, Handle<Map>(transition));
Handle<Code> ic(Builtins::builtin(storage_extend));
__ Jump(ic, RelocInfo::CODE_TARGET);
return;
}
if (transition != NULL) {
// Update the map of the object; no write barrier updating is
// needed because the map is never in new space.
__ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset),
Handle<Map>(transition));
}
// Adjust for the number of properties stored in the object. Even in the
// face of a transition we can use the old map here because the size of the
// object and the number of in-object properties is not going to change.
index -= object->map()->inobject_properties();
if (index < 0) {
// Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize);
__ movq(FieldOperand(receiver_reg, offset), rax);
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
__ movq(name_reg, rax);
__ RecordWrite(receiver_reg, offset, name_reg, scratch);
} else {
// Write to the properties array.
int offset = index * kPointerSize + FixedArray::kHeaderSize;
// Get the properties array (optimistically).
__ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
__ movq(FieldOperand(scratch, offset), rax);
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
__ movq(name_reg, rax);
__ RecordWrite(scratch, offset, name_reg, receiver_reg);
}
// Return the value (register rax).
__ ret(0);
}
#undef __ #undef __