Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 149066: X64 Implementation: Correct type, add VisitCallEval (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 ExternalReference stack_guard_limit = 497 ExternalReference stack_guard_limit =
498 ExternalReference::address_of_stack_guard_limit(); 498 ExternalReference::address_of_stack_guard_limit();
499 __ movq(kScratchRegister, stack_guard_limit); 499 __ movq(kScratchRegister, stack_guard_limit);
500 __ cmpq(rsp, Operand(kScratchRegister, 0)); 500 __ cmpq(rsp, Operand(kScratchRegister, 0));
501 deferred->Branch(below); 501 deferred->Branch(below);
502 deferred->BindExit(); 502 deferred->BindExit();
503 } 503 }
504 } 504 }
505 505
506 506
507 class CallFunctionStub: public CodeStub {
508 public:
509 CallFunctionStub(int argc, InLoopFlag in_loop)
510 : argc_(argc), in_loop_(in_loop) { }
511
512 void Generate(MacroAssembler* masm);
513
514 private:
515 int argc_;
516 InLoopFlag in_loop_;
517
518 #ifdef DEBUG
519 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
520 #endif
521
522 Major MajorKey() { return CallFunction; }
523 int MinorKey() { return argc_; }
524 InLoopFlag InLoop() { return in_loop_; }
525 };
526
527
507 void CodeGenerator::VisitAndSpill(Statement* statement) { 528 void CodeGenerator::VisitAndSpill(Statement* statement) {
508 // TODO(X64): No architecture specific code. Move to shared location. 529 // TODO(X64): No architecture specific code. Move to shared location.
509 ASSERT(in_spilled_code()); 530 ASSERT(in_spilled_code());
510 set_in_spilled_code(false); 531 set_in_spilled_code(false);
511 Visit(statement); 532 Visit(statement);
512 if (frame_ != NULL) { 533 if (frame_ != NULL) {
513 frame_->SpillAll(); 534 frame_->SpillAll();
514 } 535 }
515 set_in_spilled_code(true); 536 set_in_spilled_code(true);
516 } 537 }
(...skipping 1961 matching lines...) Expand 10 before | Expand all | Expand 10 after
2478 2499
2479 // Pass the global proxy as the receiver. 2500 // Pass the global proxy as the receiver.
2480 LoadGlobalReceiver(); 2501 LoadGlobalReceiver();
2481 2502
2482 // Call the function. 2503 // Call the function.
2483 CallWithArguments(args, node->position()); 2504 CallWithArguments(args, node->position());
2484 } 2505 }
2485 } 2506 }
2486 2507
2487 2508
2488 void CodeGenerator::VisitCallEval(CallEval* a) { 2509 void CodeGenerator::VisitCallEval(CallEval* node) {
2489 UNIMPLEMENTED(); 2510 Comment cmnt(masm_, "[ CallEval");
2511
2512 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve
2513 // the function we need to call and the receiver of the call.
2514 // Then we call the resolved function using the given arguments.
2515
2516 ZoneList<Expression*>* args = node->arguments();
2517 Expression* function = node->expression();
2518
2519 CodeForStatementPosition(node);
2520
2521 // Prepare the stack for the call to the resolved function.
2522 Load(function);
2523
2524 // Allocate a frame slot for the receiver.
2525 frame_->Push(Factory::undefined_value());
2526 int arg_count = args->length();
2527 for (int i = 0; i < arg_count; i++) {
2528 Load(args->at(i));
2529 }
2530
2531 // Prepare the stack for the call to ResolvePossiblyDirectEval.
2532 frame_->PushElementAt(arg_count + 1);
2533 if (arg_count > 0) {
2534 frame_->PushElementAt(arg_count);
2535 } else {
2536 frame_->Push(Factory::undefined_value());
2537 }
2538
2539 // Resolve the call.
2540 Result result =
2541 frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2);
2542
2543 // Touch up the stack with the right values for the function and the
2544 // receiver. Use a scratch register to avoid destroying the result.
2545 Result scratch = allocator_->Allocate();
2546 ASSERT(scratch.is_valid());
2547 __ movl(scratch.reg(),
2548 FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(0)));
2549 frame_->SetElementAt(arg_count + 1, &scratch);
2550
2551 // We can reuse the result register now.
2552 frame_->Spill(result.reg());
2553 __ movl(result.reg(),
2554 FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(1)));
2555 frame_->SetElementAt(arg_count, &result);
2556
2557 // Call the function.
2558 CodeForSourcePosition(node->position());
2559 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
2560 CallFunctionStub call_function(arg_count, in_loop);
2561 result = frame_->CallStub(&call_function, arg_count + 1);
2562
2563 // Restore the context and overwrite the function on the stack with
2564 // the result.
2565 frame_->RestoreContextRegister();
2566 frame_->SetElementAt(0, &result);
2490 } 2567 }
2491 2568
2492 2569
2493 void CodeGenerator::VisitCallNew(CallNew* node) { 2570 void CodeGenerator::VisitCallNew(CallNew* node) {
2494 Comment cmnt(masm_, "[ CallNew"); 2571 Comment cmnt(masm_, "[ CallNew");
2495 CodeForStatementPosition(node); 2572 CodeForStatementPosition(node);
2496 2573
2497 // According to ECMA-262, section 11.2.2, page 44, the function 2574 // According to ECMA-262, section 11.2.2, page 44, the function
2498 // expression in new calls must be evaluated before the 2575 // expression in new calls must be evaluated before the
2499 // arguments. This is different from ordinary calls, where the 2576 // arguments. This is different from ordinary calls, where the
(...skipping 1235 matching lines...) Expand 10 before | Expand all | Expand 10 after
3735 3812
3736 slow.Bind(); 3813 slow.Bind();
3737 // A runtime call is inevitable. We eagerly sync frame elements 3814 // A runtime call is inevitable. We eagerly sync frame elements
3738 // to memory so that we can push the arguments directly into place 3815 // to memory so that we can push the arguments directly into place
3739 // on top of the frame. 3816 // on top of the frame.
3740 frame_->SyncRange(0, frame_->element_count() - 1); 3817 frame_->SyncRange(0, frame_->element_count() - 1);
3741 frame_->EmitPush(rsi); 3818 frame_->EmitPush(rsi);
3742 __ movq(kScratchRegister, slot->var()->name(), RelocInfo::EMBEDDED_OBJECT); 3819 __ movq(kScratchRegister, slot->var()->name(), RelocInfo::EMBEDDED_OBJECT);
3743 frame_->EmitPush(kScratchRegister); 3820 frame_->EmitPush(kScratchRegister);
3744 if (typeof_state == INSIDE_TYPEOF) { 3821 if (typeof_state == INSIDE_TYPEOF) {
3745 // value = 3822 value =
3746 // frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3823 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3747 } else { 3824 } else {
3748 // value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 3825 value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
3749 } 3826 }
3750 3827
3751 done.Bind(&value); 3828 done.Bind(&value);
3752 frame_->Push(&value); 3829 frame_->Push(&value);
3753 3830
3754 } else if (slot->var()->mode() == Variable::CONST) { 3831 } else if (slot->var()->mode() == Variable::CONST) {
3755 // Const slots may contain 'the hole' value (the constant hasn't been 3832 // Const slots may contain 'the hole' value (the constant hasn't been
3756 // initialized yet) which needs to be converted into the 'undefined' 3833 // initialized yet) which needs to be converted into the 'undefined'
3757 // value. 3834 // value.
3758 // 3835 //
(...skipping 1823 matching lines...) Expand 10 before | Expand all | Expand 10 after
5582 __ j(zero, label); 5659 __ j(zero, label);
5583 __ movq(kScratchRegister, FieldOperand(object, HeapObject::kMapOffset)); 5660 __ movq(kScratchRegister, FieldOperand(object, HeapObject::kMapOffset));
5584 __ movzxbq(kScratchRegister, 5661 __ movzxbq(kScratchRegister,
5585 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); 5662 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
5586 __ and_(kScratchRegister, Immediate(kIsSymbolMask | kIsNotStringMask)); 5663 __ and_(kScratchRegister, Immediate(kIsSymbolMask | kIsNotStringMask));
5587 __ cmpb(kScratchRegister, Immediate(kSymbolTag | kStringTag)); 5664 __ cmpb(kScratchRegister, Immediate(kSymbolTag | kStringTag));
5588 __ j(not_equal, label); 5665 __ j(not_equal, label);
5589 } 5666 }
5590 5667
5591 5668
5592 class CallFunctionStub: public CodeStub {
5593 public:
5594 CallFunctionStub(int argc, InLoopFlag in_loop)
5595 : argc_(argc), in_loop_(in_loop) { }
5596
5597 void Generate(MacroAssembler* masm);
5598
5599 private:
5600 int argc_;
5601 InLoopFlag in_loop_;
5602
5603 #ifdef DEBUG
5604 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
5605 #endif
5606
5607 Major MajorKey() { return CallFunction; }
5608 int MinorKey() { return argc_; }
5609 InLoopFlag InLoop() { return in_loop_; }
5610 };
5611
5612
5613 void CallFunctionStub::Generate(MacroAssembler* masm) {
5614 Label slow;
5615
5616 // Get the function to call from the stack.
5617 // +2 ~ receiver, return address
5618 __ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize));
5619
5620 // Check that the function really is a JavaScript function.
5621 __ testl(rdi, Immediate(kSmiTagMask));
5622 __ j(zero, &slow);
5623 // Goto slow case if we do not have a function.
5624 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
5625 __ j(not_equal, &slow);
5626
5627 // Fast-case: Just invoke the function.
5628 ParameterCount actual(argc_);
5629 __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
5630
5631 // Slow-case: Non-function called.
5632 __ bind(&slow);
5633 __ Set(rax, argc_);
5634 __ Set(rbx, 0);
5635 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
5636 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
5637 __ Jump(adaptor, RelocInfo::CODE_TARGET);
5638 }
5639
5640
5641 // Call the function just below TOS on the stack with the given 5669 // Call the function just below TOS on the stack with the given
5642 // arguments. The receiver is the TOS. 5670 // arguments. The receiver is the TOS.
5643 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 5671 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
5644 int position) { 5672 int position) {
5645 // Push the arguments ("left-to-right") on the stack. 5673 // Push the arguments ("left-to-right") on the stack.
5646 int arg_count = args->length(); 5674 int arg_count = args->length();
5647 for (int i = 0; i < arg_count; i++) { 5675 for (int i = 0; i < arg_count; i++) {
5648 Load(args->at(i)); 5676 Load(args->at(i));
5649 } 5677 }
5650 5678
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5684 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 5712 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
5685 __ movq(Operand(rsp, 1 * kPointerSize), rcx); 5713 __ movq(Operand(rsp, 1 * kPointerSize), rcx);
5686 __ lea(rdx, Operand(rdx, rcx, times_4, kDisplacement)); 5714 __ lea(rdx, Operand(rdx, rcx, times_4, kDisplacement));
5687 __ movq(Operand(rsp, 2 * kPointerSize), rdx); 5715 __ movq(Operand(rsp, 2 * kPointerSize), rdx);
5688 5716
5689 // Do the runtime call to allocate the arguments object. 5717 // Do the runtime call to allocate the arguments object.
5690 __ bind(&runtime); 5718 __ bind(&runtime);
5691 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); 5719 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3);
5692 } 5720 }
5693 5721
5722
5694 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 5723 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
5695 // The key is in rdx and the parameter count is in rax. 5724 // The key is in rdx and the parameter count is in rax.
5696 5725
5697 // The displacement is used for skipping the frame pointer on the 5726 // The displacement is used for skipping the frame pointer on the
5698 // stack. It is the offset of the last parameter (if any) relative 5727 // stack. It is the offset of the last parameter (if any) relative
5699 // to the frame pointer. 5728 // to the frame pointer.
5700 static const int kDisplacement = 1 * kPointerSize; 5729 static const int kDisplacement = 1 * kPointerSize;
5701 5730
5702 // Check that the key is a smi. 5731 // Check that the key is a smi.
5703 Label slow; 5732 Label slow;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
5798 Label skip; 5827 Label skip;
5799 __ cmpq(rbp, Immediate(0)); 5828 __ cmpq(rbp, Immediate(0));
5800 __ j(equal, &skip); 5829 __ j(equal, &skip);
5801 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 5830 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
5802 __ bind(&skip); 5831 __ bind(&skip);
5803 5832
5804 __ ret(0); 5833 __ ret(0);
5805 } 5834 }
5806 5835
5807 5836
5808
5809 void CEntryStub::GenerateCore(MacroAssembler* masm, 5837 void CEntryStub::GenerateCore(MacroAssembler* masm,
5810 Label* throw_normal_exception, 5838 Label* throw_normal_exception,
5811 Label* throw_out_of_memory_exception, 5839 Label* throw_out_of_memory_exception,
5812 StackFrame::Type frame_type, 5840 StackFrame::Type frame_type,
5813 bool do_gc, 5841 bool do_gc,
5814 bool always_allocate_scope) { 5842 bool always_allocate_scope) {
5815 // rax: result parameter for PerformGC, if any. 5843 // rax: result parameter for PerformGC, if any.
5816 // rbx: pointer to C function (C callee-saved). 5844 // rbx: pointer to C function (C callee-saved).
5817 // rbp: frame pointer (restored after C call). 5845 // rbp: frame pointer (restored after C call).
5818 // rsp: stack pointer (restored after C call). 5846 // rsp: stack pointer (restored after C call).
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
5947 ASSERT_EQ(StackHandlerConstants::kFPOffset + kPointerSize, 5975 ASSERT_EQ(StackHandlerConstants::kFPOffset + kPointerSize,
5948 StackHandlerConstants::kStateOffset); 5976 StackHandlerConstants::kStateOffset);
5949 __ pop(rdx); // State 5977 __ pop(rdx); // State
5950 5978
5951 ASSERT_EQ(StackHandlerConstants::kStateOffset + kPointerSize, 5979 ASSERT_EQ(StackHandlerConstants::kStateOffset + kPointerSize,
5952 StackHandlerConstants::kPCOffset); 5980 StackHandlerConstants::kPCOffset);
5953 __ ret(0); 5981 __ ret(0);
5954 } 5982 }
5955 5983
5956 5984
5985 void CallFunctionStub::Generate(MacroAssembler* masm) {
5986 Label slow;
5987
5988 // Get the function to call from the stack.
5989 // +2 ~ receiver, return address
5990 __ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize));
5991
5992 // Check that the function really is a JavaScript function.
5993 __ testl(rdi, Immediate(kSmiTagMask));
5994 __ j(zero, &slow);
5995 // Goto slow case if we do not have a function.
5996 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
5997 __ j(not_equal, &slow);
5998
5999 // Fast-case: Just invoke the function.
6000 ParameterCount actual(argc_);
6001 __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
6002
6003 // Slow-case: Non-function called.
6004 __ bind(&slow);
6005 __ Set(rax, argc_);
6006 __ Set(rbx, 0);
6007 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
6008 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
6009 __ Jump(adaptor, RelocInfo::CODE_TARGET);
6010 }
6011
6012
5957 void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { 6013 void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
5958 // rax: number of arguments including receiver 6014 // rax: number of arguments including receiver
5959 // rbx: pointer to C function (C callee-saved) 6015 // rbx: pointer to C function (C callee-saved)
5960 // rbp: frame pointer (restored after C call) 6016 // rbp: frame pointer (restored after C call)
5961 // rsp: stack pointer (restored after C call) 6017 // rsp: stack pointer (restored after C call)
5962 // rsi: current context (C callee-saved) 6018 // rsi: current context (C callee-saved)
5963 // rdi: caller's parameter pointer pp (C callee-saved) 6019 // rdi: caller's parameter pointer pp (C callee-saved)
5964 6020
5965 // NOTE: Invocations of builtins may return failure objects 6021 // NOTE: Invocations of builtins may return failure objects
5966 // instead of a proper result. The builtin entry handles 6022 // instead of a proper result. The builtin entry handles
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
6241 __ bind(&done_load_lhs); 6297 __ bind(&done_load_lhs);
6242 6298
6243 __ testl(rhs, Immediate(kSmiTagMask)); 6299 __ testl(rhs, Immediate(kSmiTagMask));
6244 __ j(zero, &load_smi_rhs); 6300 __ j(zero, &load_smi_rhs);
6245 __ fld_d(FieldOperand(rhs, HeapNumber::kValueOffset)); 6301 __ fld_d(FieldOperand(rhs, HeapNumber::kValueOffset));
6246 __ jmp(&done); 6302 __ jmp(&done);
6247 6303
6248 __ bind(&load_smi_lhs); 6304 __ bind(&load_smi_lhs);
6249 ASSERT(kSmiTagSize == 1); 6305 ASSERT(kSmiTagSize == 1);
6250 ASSERT(kSmiTag == 0); 6306 ASSERT(kSmiTag == 0);
6251 __ lea(kScratchRegister, Operand(lhs, lhs, times_1, 0); 6307 __ lea(kScratchRegister, Operand(lhs, lhs, times_1, 0));
6252 __ push(kScratchRegister); 6308 __ push(kScratchRegister);
6253 __ fild_s(Operand(rsp, 0)); 6309 __ fild_s(Operand(rsp, 0));
6254 __ pop(kScratchRegister); 6310 __ pop(kScratchRegister);
6255 __ jmp(&done_load_lhs); 6311 __ jmp(&done_load_lhs);
6256 6312
6257 __ bind(&load_smi_rhs); 6313 __ bind(&load_smi_rhs);
6258 __ movq(kScratchRegister, rhs); 6314 __ movq(kScratchRegister, rhs);
6259 __ sar(kScratchRegister, Immediate(kSmiTagSize)); 6315 __ sar(kScratchRegister, Immediate(kSmiTagSize));
6260 __ push(kScratchRegister); 6316 __ push(kScratchRegister);
6261 __ fild_s(Operand(rsp, 0)); 6317 __ fild_s(Operand(rsp, 0));
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after
6700 break; 6756 break;
6701 default: 6757 default:
6702 UNREACHABLE(); 6758 UNREACHABLE();
6703 } 6759 }
6704 } 6760 }
6705 6761
6706 6762
6707 #undef __ 6763 #undef __
6708 6764
6709 } } // namespace v8::internal 6765 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698