-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
- // REgister state for IC store call (from ic-ia32.cc).
+ // Register state for IC store call (from ic-ia32.cc).
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
+ // -- edx : receiver
// -----------------------------------
- Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false);
+ Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit() | edx.bit(), false);
}
Load(property->value());
frame_->Push(key);
Result ignored = frame_->CallStoreIC();
- // Drop the duplicated receiver and ignore the result.
- frame_->Drop();
break;
}
// Fall through
cgen_->frame()->Push(GetName());
Result answer = cgen_->frame()->CallStoreIC();
cgen_->frame()->Push(&answer);
- cgen_->UnloadReference(this);
+ set_unloaded();
break;
}
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
- // REgister state for IC store call (from ic-x64.cc).
+ // Register state for IC store call (from ic-x64.cc).
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
+ // -- rdx : receiver
// -----------------------------------
- Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), false);
+ Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit() | rdx.bit(), false);
}
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
if (key->handle()->IsSymbol()) {
VisitForValue(value, kAccumulator);
__ Move(rcx, key->handle());
+ __ movq(rdx, Operand(rsp, 0));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET);
__ nop();
- // StoreIC leaves the receiver on the stack.
break;
}
// Fall through.
ASSERT(!var->is_this());
// Assignment to a global variable. Use inline caching for the
// assignment. Right-hand-side value is passed in rax, variable name in
- // rcx, and the global object on the stack.
+ // rcx, and the global object in rdx.
__ Move(rcx, var->name());
- __ push(CodeGenerator::GlobalObject());
+ __ movq(rdx, CodeGenerator::GlobalObject());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
- // Overwrite the global object on the stack with the result if needed.
- DropAndApply(1, context, rax);
+ Apply(context, rax);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
__ push(result_register()); // Value.
// Record source code position before IC call.
SetSourcePosition(expr->position());
__ Move(rcx, prop->key()->AsLiteral()->handle());
+ if (expr->ends_initialization_block()) {
+ __ movq(rdx, Operand(rsp, 0));
+ } else {
+ __ pop(rdx);
+ }
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
__ nop();
__ push(Operand(rsp, kPointerSize)); // Receiver is under value.
__ CallRuntime(Runtime::kToFastProperties, 1);
__ pop(rax);
+ DropAndApply(1, context_, rax);
+ } else {
+ Apply(context_, rax);
}
-
- DropAndApply(1, context_, rax);
}
break;
case NAMED_PROPERTY: {
__ Move(rcx, prop->key()->AsLiteral()->handle());
+ __ pop(rdx);
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET);
// This nop signals to the IC that there is no inlined code at the call
// site for it to patch.
__ nop();
if (expr->is_postfix()) {
- __ Drop(1); // Result is on the stack under the receiver.
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
- DropAndApply(1, context_, rax);
+ Apply(context_, rax);
}
break;
}
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
+ // -- rdx : receiver
// -- rsp[0] : return address
- // -- rsp[8] : receiver
// -----------------------------------
__ pop(rbx);
- __ push(Operand(rsp, 0)); // receiver
+ __ push(rdx); // receiver
__ push(rcx); // name
__ push(rax); // value
__ push(rbx); // return address
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : Map (target of map transition)
+ // -- rdx : receiver
// -- rsp[0] : return address
- // -- rsp[8] : receiver
// -----------------------------------
__ pop(rbx);
- __ push(Operand(rsp, 0)); // receiver
+ __ push(rdx); // receiver
__ push(rcx); // transition map
__ push(rax); // value
__ push(rbx); // return address
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
+ // -- rdx : receiver
// -- rsp[0] : return address
- // -- rsp[8] : receiver
// -----------------------------------
// Get the receiver from the stack and probe the stub cache.
- __ movq(rdx, Operand(rsp, kPointerSize));
Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
NOT_IN_LOOP,
MONOMORPHIC);
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
+ // -- rdx : receiver
// -- rsp[0] : return address
- // -- rsp[8] : receiver
// -----------------------------------
Label miss;
- // Get the object from the stack.
- __ movq(rbx, Operand(rsp, 1 * kPointerSize));
-
// Check that the object isn't a smi.
- __ JumpIfSmi(rbx, &miss);
+ __ JumpIfSmi(rdx, &miss);
// Check that the map of the object hasn't changed.
- __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
+ __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
Handle<Map>(object->map()));
__ j(not_equal, &miss);
// Perform global security token check if needed.
if (object->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(rbx, rdx, &miss);
+ __ CheckAccessGlobalProxy(rdx, rbx, &miss);
}
// Stub never generated for non-global objects that require access
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ pop(rbx); // remove the return address
- __ push(Operand(rsp, 0)); // receiver
+ __ push(rdx); // receiver
__ Push(Handle<AccessorInfo>(callback)); // callback info
__ push(rcx); // name
__ push(rax); // value
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
+ // -- rdx : receiver
// -- 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,
+ rdx, rcx, rbx,
&miss);
// Handle store cache miss.
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
+ // -- rdx : receiver
// -- rsp[0] : return address
- // -- rsp[8] : receiver
// -----------------------------------
Label miss;
- // Get the object from the stack.
- __ movq(rbx, Operand(rsp, 1 * kPointerSize));
-
// Check that the object isn't a smi.
- __ JumpIfSmi(rbx, &miss);
+ __ JumpIfSmi(rdx, &miss);
// Check that the map of the object hasn't changed.
- __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
+ __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
Handle<Map>(receiver->map()));
__ j(not_equal, &miss);
// Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(rbx, rdx, &miss);
+ __ CheckAccessGlobalProxy(rdx, rbx, &miss);
}
// Stub never generated for non-global objects that require access
ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
__ pop(rbx); // remove the return address
- __ push(Operand(rsp, 0)); // receiver
+ __ push(rdx); // receiver
__ push(rcx); // name
__ push(rax); // value
__ push(rbx); // restore return address
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
+ // -- rdx : receiver
// -- rsp[0] : return address
- // -- rsp[8] : receiver
// -----------------------------------
Label miss;
// Check that the map of the global has not changed.
- __ movq(rbx, Operand(rsp, kPointerSize));
- __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
+ __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
Handle<Map>(object->map()));
__ j(not_equal, &miss);
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
Result VirtualFrame::CallStoreIC() {
// Name, value, and receiver are on top of the frame. The IC
- // expects name in rcx, value in rax, and receiver on the stack. It
- // does not drop the receiver.
+ // expects name in rcx, value in rax, and receiver in edx.
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
Result name = Pop();
Result value = Pop();
- PrepareForCall(1, 0); // One stack arg, not callee-dropped.
+ Result receiver = Pop();
+ PrepareForCall(0, 0);
- if (value.is_register() && value.reg().is(rcx)) {
- if (name.is_register() && name.reg().is(rax)) {
+ // Optimized for case in which name is a constant value.
+ if (name.is_register() && (name.reg().is(rdx) || name.reg().is(rax))) {
+ if (!is_used(rcx)) {
+ name.ToRegister(rcx);
+ } else if (!is_used(rbx)) {
+ name.ToRegister(rbx);
+ } else {
+ ASSERT(!is_used(rdi)); // Only three results are live, so rdi is free.
+ name.ToRegister(rdi);
+ }
+ }
+ // Now name is not in edx or eax, so we can fix them, then move name to ecx.
+ if (value.is_register() && value.reg().is(rdx)) {
+ if (receiver.is_register() && receiver.reg().is(rax)) {
// Wrong registers.
- __ xchg(rax, rcx);
+ __ xchg(rax, rdx);
} else {
- // Register rax is free for value, which frees rcx for name.
+ // Register rax is free for value, which frees rcx for receiver.
value.ToRegister(rax);
- name.ToRegister(rcx);
+ receiver.ToRegister(rdx);
}
} else {
- // Register rcx is free for name, which guarantees rax is free for
+ // Register rcx is free for receiver, which guarantees rax is free for
// value.
- name.ToRegister(rcx);
+ receiver.ToRegister(rdx);
value.ToRegister(rax);
}
-
+ // Receiver and value are in the right place, so rcx is free for name.
+ name.ToRegister(rcx);
name.Unuse();
value.Unuse();
+ receiver.Unuse();
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
}