}
-Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
- InvokeFlag flag,
- int arg_count) {
+//------------------------------------------------------------------------------
+// Virtual frame stub and IC calling functions.
+
+Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
PrepareForCall(arg_count, arg_count);
ASSERT(cgen()->HasValidEntryRegisters());
- __ InvokeBuiltin(id, flag);
+ __ CallRuntime(f, arg_count);
Result result = cgen()->allocator()->Allocate(rax);
ASSERT(result.is_valid());
return result;
}
-//------------------------------------------------------------------------------
-// Virtual frame stub and IC calling functions.
-
-Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
- RelocInfo::Mode rmode) {
+Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) {
+ PrepareForCall(arg_count, arg_count);
ASSERT(cgen()->HasValidEntryRegisters());
- __ Call(code, rmode);
+ __ CallRuntime(id, arg_count);
Result result = cgen()->allocator()->Allocate(rax);
ASSERT(result.is_valid());
return result;
}
-Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
- PrepareForCall(arg_count, arg_count);
+#ifdef ENABLE_DEBUGGER_SUPPORT
+void VirtualFrame::DebugBreak() {
+ PrepareForCall(0, 0);
ASSERT(cgen()->HasValidEntryRegisters());
- __ CallRuntime(f, arg_count);
+ __ DebugBreak();
Result result = cgen()->allocator()->Allocate(rax);
ASSERT(result.is_valid());
- return result;
}
+#endif
-Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) {
+Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
+ InvokeFlag flag,
+ int arg_count) {
PrepareForCall(arg_count, arg_count);
ASSERT(cgen()->HasValidEntryRegisters());
- __ CallRuntime(id, arg_count);
+ __ InvokeBuiltin(id, flag);
Result result = cgen()->allocator()->Allocate(rax);
ASSERT(result.is_valid());
return result;
}
-#ifdef ENABLE_DEBUGGER_SUPPORT
-void VirtualFrame::DebugBreak() {
- PrepareForCall(0, 0);
+Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
+ RelocInfo::Mode rmode) {
ASSERT(cgen()->HasValidEntryRegisters());
- __ DebugBreak();
+ __ Call(code, rmode);
Result result = cgen()->allocator()->Allocate(rax);
ASSERT(result.is_valid());
+ return result;
}
-#endif
// This function assumes that the only results that could be in a_reg or b_reg
Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) {
- // Key and receiver are on top of the frame. The IC expects them on
- // the stack. It does not drop them.
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
- Result name = Pop();
+ // Key and receiver are on top of the frame. Put them in rax and rdx.
+ Result key = Pop();
Result receiver = Pop();
PrepareForCall(0, 0);
- MoveResultsToRegisters(&name, &receiver, rax, rdx);
+ MoveResultsToRegisters(&key, &receiver, rax, rdx);
+
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
return RawCallCodeObject(ic, mode);
}
-Result VirtualFrame::CallCommonStoreIC(Handle<Code> ic,
- Result* value,
- Result* key,
- Result* receiver) {
- // The IC expects value in rax, key in rcx, and receiver in rdx.
+Result VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) {
+ // Value and (if not contextual) receiver are on top of the frame.
+ // The IC expects name in rcx, value in rax, and receiver in rdx.
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+ Result value = Pop();
+ if (is_contextual) {
+ PrepareForCall(0, 0);
+ value.ToRegister(rax);
+ __ movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ value.Unuse();
+ } else {
+ Result receiver = Pop();
+ PrepareForCall(0, 0);
+ MoveResultsToRegisters(&value, &receiver, rax, rdx);
+ }
+ __ Move(rcx, name);
+ return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
+}
+
+
+Result VirtualFrame::CallKeyedStoreIC() {
+ // Value, key, and receiver are on the top of the frame. The IC
+ // expects value in rax, key in rcx, and receiver in rdx.
+ Result value = Pop();
+ Result key = Pop();
+ Result receiver = Pop();
PrepareForCall(0, 0);
- // If one of the three registers is free, or a value is already
- // in the correct register, move the remaining two values using
- // MoveResultsToRegisters().
if (!cgen()->allocator()->is_used(rax) ||
- (value->is_register() && value->reg().is(rax))) {
+ (value.is_register() && value.reg().is(rax))) {
if (!cgen()->allocator()->is_used(rax)) {
- value->ToRegister(rax);
+ value.ToRegister(rax);
}
- MoveResultsToRegisters(key, receiver, rcx, rdx);
- value->Unuse();
+ MoveResultsToRegisters(&key, &receiver, rcx, rdx);
+ value.Unuse();
} else if (!cgen()->allocator()->is_used(rcx) ||
- (key->is_register() && key->reg().is(rcx))) {
+ (key.is_register() && key.reg().is(rcx))) {
if (!cgen()->allocator()->is_used(rcx)) {
- key->ToRegister(rcx);
+ key.ToRegister(rcx);
}
- MoveResultsToRegisters(value, receiver, rax, rdx);
- key->Unuse();
+ MoveResultsToRegisters(&value, &receiver, rax, rdx);
+ key.Unuse();
} else if (!cgen()->allocator()->is_used(rdx) ||
- (receiver->is_register() && receiver->reg().is(rdx))) {
+ (receiver.is_register() && receiver.reg().is(rdx))) {
if (!cgen()->allocator()->is_used(rdx)) {
- receiver->ToRegister(rdx);
+ receiver.ToRegister(rdx);
}
- MoveResultsToRegisters(key, value, rcx, rax);
- receiver->Unuse();
+ MoveResultsToRegisters(&key, &value, rcx, rax);
+ receiver.Unuse();
} else {
- // Otherwise, no register is free, and no value is in the correct place.
- // We have one of the two circular permutations of eax, ecx, edx.
- ASSERT(value->is_register());
- if (value->reg().is(rcx)) {
+ // All three registers are used, and no value is in the correct place.
+ // We have one of the two circular permutations of rax, rcx, rdx.
+ ASSERT(value.is_register());
+ if (value.reg().is(rcx)) {
__ xchg(rax, rdx);
__ xchg(rax, rcx);
} else {
__ xchg(rax, rcx);
__ xchg(rax, rdx);
}
- value->Unuse();
- key->Unuse();
- receiver->Unuse();
- }
-
- return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
-}
-
-
-Result VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) {
- // Value and (if not contextual) receiver are on top of the frame.
- // The IC expects name in rcx, value in rax, and receiver in rdx.
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- Result value = Pop();
- if (is_contextual) {
- PrepareForCall(0, 0);
- value.ToRegister(rax);
- __ movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
value.Unuse();
- } else {
- Result receiver = Pop();
- PrepareForCall(0, 0);
- MoveResultsToRegisters(&value, &receiver, rax, rdx);
+ key.Unuse();
+ receiver.Unuse();
}
- __ Move(rcx, name);
+
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
}
int arg_count);
// Call load IC. Name and receiver are found on top of the frame.
- // Receiver is not dropped.
+ // Both are dropped.
Result CallLoadIC(RelocInfo::Mode mode);
// Call keyed load IC. Key and receiver are found on top of the
- // frame. They are not dropped.
+ // frame. Both are dropped.
Result CallKeyedLoadIC(RelocInfo::Mode mode);
-
- // Calling a store IC and a keyed store IC differ only by which ic is called
- // and by the order of the three arguments on the frame.
- Result CallCommonStoreIC(Handle<Code> ic,
- Result* value,
- Result* key,
- Result* receiver);
-
- // Call store IC. Name, value, and receiver are found on top
- // of the frame. All are dropped.
- Result CallStoreIC() {
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- Result name = Pop();
- Result value = Pop();
- Result receiver = Pop();
- return CallCommonStoreIC(ic, &value, &name, &receiver);
- }
-
// Call store IC. If the load is contextual, value is found on top of the
// frame. If not, value and receiver are on the frame. Both are dropped.
Result CallStoreIC(Handle<String> name, bool is_contextual);
// Call keyed store IC. Value, key, and receiver are found on top
- // of the frame. All are dropped.
- Result CallKeyedStoreIC() {
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
- Result value = Pop();
- Result key = Pop();
- Result receiver = Pop();
- return CallCommonStoreIC(ic, &value, &key, &receiver);
- }
+ // of the frame. All three are dropped.
+ Result CallKeyedStoreIC();
// Call call IC. Function name, arguments, and receiver are found on top
// of the frame and dropped by the call.
// The argument count does not include the receiver.
Result CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting);
+ // Call keyed call IC. Same calling convention as CallCallIC.
Result CallKeyedCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting);
// Allocate and call JS function as constructor. Arguments,