Commit 0746d930 authored by whesse@chromium.org's avatar whesse@chromium.org

X64 Implementation: Correct type, add VisitCallEval

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2282 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1ad12de4
...@@ -1639,6 +1639,9 @@ class FixedArray: public Array { ...@@ -1639,6 +1639,9 @@ class FixedArray: public Array {
// Garbage collection support. // Garbage collection support.
static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; } static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; }
// Code Generation support.
static int OffsetOfElementAt(int index) { return SizeFor(index); }
// Casting. // Casting.
static inline FixedArray* cast(Object* obj); static inline FixedArray* cast(Object* obj);
......
...@@ -504,6 +504,27 @@ void CodeGenerator::CheckStack() { ...@@ -504,6 +504,27 @@ void CodeGenerator::CheckStack() {
} }
class CallFunctionStub: public CodeStub {
public:
CallFunctionStub(int argc, InLoopFlag in_loop)
: argc_(argc), in_loop_(in_loop) { }
void Generate(MacroAssembler* masm);
private:
int argc_;
InLoopFlag in_loop_;
#ifdef DEBUG
void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
#endif
Major MajorKey() { return CallFunction; }
int MinorKey() { return argc_; }
InLoopFlag InLoop() { return in_loop_; }
};
void CodeGenerator::VisitAndSpill(Statement* statement) { void CodeGenerator::VisitAndSpill(Statement* statement) {
// TODO(X64): No architecture specific code. Move to shared location. // TODO(X64): No architecture specific code. Move to shared location.
ASSERT(in_spilled_code()); ASSERT(in_spilled_code());
...@@ -2485,8 +2506,64 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2485,8 +2506,64 @@ void CodeGenerator::VisitCall(Call* node) {
} }
void CodeGenerator::VisitCallEval(CallEval* a) { void CodeGenerator::VisitCallEval(CallEval* node) {
UNIMPLEMENTED(); Comment cmnt(masm_, "[ CallEval");
// In a call to eval, we first call %ResolvePossiblyDirectEval to resolve
// the function we need to call and the receiver of the call.
// Then we call the resolved function using the given arguments.
ZoneList<Expression*>* args = node->arguments();
Expression* function = node->expression();
CodeForStatementPosition(node);
// Prepare the stack for the call to the resolved function.
Load(function);
// Allocate a frame slot for the receiver.
frame_->Push(Factory::undefined_value());
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Load(args->at(i));
}
// Prepare the stack for the call to ResolvePossiblyDirectEval.
frame_->PushElementAt(arg_count + 1);
if (arg_count > 0) {
frame_->PushElementAt(arg_count);
} else {
frame_->Push(Factory::undefined_value());
}
// Resolve the call.
Result result =
frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2);
// Touch up the stack with the right values for the function and the
// receiver. Use a scratch register to avoid destroying the result.
Result scratch = allocator_->Allocate();
ASSERT(scratch.is_valid());
__ movl(scratch.reg(),
FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(0)));
frame_->SetElementAt(arg_count + 1, &scratch);
// We can reuse the result register now.
frame_->Spill(result.reg());
__ movl(result.reg(),
FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(1)));
frame_->SetElementAt(arg_count, &result);
// Call the function.
CodeForSourcePosition(node->position());
InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
CallFunctionStub call_function(arg_count, in_loop);
result = frame_->CallStub(&call_function, arg_count + 1);
// Restore the context and overwrite the function on the stack with
// the result.
frame_->RestoreContextRegister();
frame_->SetElementAt(0, &result);
} }
...@@ -3742,10 +3819,10 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -3742,10 +3819,10 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
__ movq(kScratchRegister, slot->var()->name(), RelocInfo::EMBEDDED_OBJECT); __ movq(kScratchRegister, slot->var()->name(), RelocInfo::EMBEDDED_OBJECT);
frame_->EmitPush(kScratchRegister); frame_->EmitPush(kScratchRegister);
if (typeof_state == INSIDE_TYPEOF) { if (typeof_state == INSIDE_TYPEOF) {
// value = value =
// frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
} else { } else {
// value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2); value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
} }
done.Bind(&value); done.Bind(&value);
...@@ -5589,55 +5666,6 @@ void CompareStub::BranchIfNonSymbol(MacroAssembler* masm, ...@@ -5589,55 +5666,6 @@ void CompareStub::BranchIfNonSymbol(MacroAssembler* masm,
} }
class CallFunctionStub: public CodeStub {
public:
CallFunctionStub(int argc, InLoopFlag in_loop)
: argc_(argc), in_loop_(in_loop) { }
void Generate(MacroAssembler* masm);
private:
int argc_;
InLoopFlag in_loop_;
#ifdef DEBUG
void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
#endif
Major MajorKey() { return CallFunction; }
int MinorKey() { return argc_; }
InLoopFlag InLoop() { return in_loop_; }
};
void CallFunctionStub::Generate(MacroAssembler* masm) {
Label slow;
// Get the function to call from the stack.
// +2 ~ receiver, return address
__ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize));
// Check that the function really is a JavaScript function.
__ testl(rdi, Immediate(kSmiTagMask));
__ j(zero, &slow);
// Goto slow case if we do not have a function.
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &slow);
// Fast-case: Just invoke the function.
ParameterCount actual(argc_);
__ InvokeFunction(rdi, actual, JUMP_FUNCTION);
// Slow-case: Non-function called.
__ bind(&slow);
__ Set(rax, argc_);
__ Set(rbx, 0);
__ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
__ Jump(adaptor, RelocInfo::CODE_TARGET);
}
// Call the function just below TOS on the stack with the given // Call the function just below TOS on the stack with the given
// arguments. The receiver is the TOS. // arguments. The receiver is the TOS.
void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
...@@ -5691,6 +5719,7 @@ void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { ...@@ -5691,6 +5719,7 @@ void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
__ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3);
} }
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
// The key is in rdx and the parameter count is in rax. // The key is in rdx and the parameter count is in rax.
...@@ -5805,7 +5834,6 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { ...@@ -5805,7 +5834,6 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
} }
void CEntryStub::GenerateCore(MacroAssembler* masm, void CEntryStub::GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception, Label* throw_normal_exception,
Label* throw_out_of_memory_exception, Label* throw_out_of_memory_exception,
...@@ -5954,6 +5982,34 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) { ...@@ -5954,6 +5982,34 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
} }
void CallFunctionStub::Generate(MacroAssembler* masm) {
Label slow;
// Get the function to call from the stack.
// +2 ~ receiver, return address
__ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize));
// Check that the function really is a JavaScript function.
__ testl(rdi, Immediate(kSmiTagMask));
__ j(zero, &slow);
// Goto slow case if we do not have a function.
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &slow);
// Fast-case: Just invoke the function.
ParameterCount actual(argc_);
__ InvokeFunction(rdi, actual, JUMP_FUNCTION);
// Slow-case: Non-function called.
__ bind(&slow);
__ Set(rax, argc_);
__ Set(rbx, 0);
__ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
__ Jump(adaptor, RelocInfo::CODE_TARGET);
}
void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// rax: number of arguments including receiver // rax: number of arguments including receiver
// rbx: pointer to C function (C callee-saved) // rbx: pointer to C function (C callee-saved)
...@@ -6248,7 +6304,7 @@ void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, ...@@ -6248,7 +6304,7 @@ void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
__ bind(&load_smi_lhs); __ bind(&load_smi_lhs);
ASSERT(kSmiTagSize == 1); ASSERT(kSmiTagSize == 1);
ASSERT(kSmiTag == 0); ASSERT(kSmiTag == 0);
__ lea(kScratchRegister, Operand(lhs, lhs, times_1, 0); __ lea(kScratchRegister, Operand(lhs, lhs, times_1, 0));
__ push(kScratchRegister); __ push(kScratchRegister);
__ fild_s(Operand(rsp, 0)); __ fild_s(Operand(rsp, 0));
__ pop(kScratchRegister); __ pop(kScratchRegister);
......
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