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

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

Issue 131029: X64 implementation: Add function literals and function calls. (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
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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 #define __ ACCESS_MASM(masm_) 96 #define __ ACCESS_MASM(masm_)
97 97
98 98
99 void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) { 99 void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) {
100 UNIMPLEMENTED(); 100 UNIMPLEMENTED();
101 } 101 }
102 102
103 void CodeGenerator::TestCodeGenerator() { 103 void CodeGenerator::TestCodeGenerator() {
104 // Compile a function from a string, and run it. 104 // Compile a function from a string, and run it.
105 Handle<JSFunction> test_function = Compiler::Compile( 105 Handle<JSFunction> test_function = Compiler::Compile(
106 Factory::NewStringFromAscii(CStrVector("39; 42;")), 106 Factory::NewStringFromAscii(CStrVector(
107 "39;"
108 "(function(){return 43})();"
109 "42;"
110 // "function foo(x, y){return x;};"
111 "43;"
112 // "foo(2,3);"
113 "44;"
114 "(function(){return (function(){return 47})()})();")),
107 Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")), 115 Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")),
108 0, 116 0,
109 0, 117 0,
110 NULL, 118 NULL,
111 NULL); 119 NULL);
112 120
113 Code* code_object = test_function->code(); // Local for debugging ease. 121 Code* code_object = test_function->code(); // Local for debugging ease.
114 USE(code_object); 122 USE(code_object);
115 123
116 // Create a dummy function and context. 124 // Create a dummy function and context.
117 Handle<JSFunction> bridge = 125 Handle<JSFunction> bridge =
118 Factory::NewFunction(Factory::empty_symbol(), Factory::undefined_value()); 126 Factory::NewFunction(Factory::empty_symbol(), Factory::undefined_value());
119 Handle<Context> context = 127 Handle<Context> context =
120 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge); 128 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge);
121 129
122 test_function = Factory::NewFunctionFromBoilerplate( 130 test_function = Factory::NewFunctionFromBoilerplate(
123 test_function, 131 test_function,
124 context); 132 context);
125 133
126 bool pending_exceptions; 134 bool pending_exceptions;
127 Handle<Object> result = 135 Handle<Object> result =
128 Execution::Call(test_function, 136 Execution::Call(test_function,
129 Handle<Object>::cast(test_function), 137 Handle<Object>::cast(test_function),
130 0, 138 0,
131 NULL, 139 NULL,
132 &pending_exceptions); 140 &pending_exceptions);
133 // Function compiles and runs, but returns a JSFunction object. 141 // Function compiles and runs, but returns a JSFunction object.
134 CHECK(result->IsSmi()); 142 CHECK(result->IsSmi());
135 CHECK_EQ(42, Smi::cast(*result)->value()); 143 CHECK_EQ(47, Smi::cast(*result)->value());
136 } 144 }
137 145
138 146
139 void CodeGenerator::GenCode(FunctionLiteral* function) { 147 void CodeGenerator::GenCode(FunctionLiteral* function) {
140 // Record the position for debugging purposes. 148 // Record the position for debugging purposes.
141 CodeForFunctionPosition(function); 149 CodeForFunctionPosition(function);
142 ZoneList<Statement*>* body = function->body(); 150 ZoneList<Statement*>* body = function->body();
143 151
144 // Initialize state. 152 // Initialize state.
145 ASSERT(scope_ == NULL); 153 ASSERT(scope_ == NULL);
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 } 371 }
364 372
365 void CodeGenerator::VisitTryFinally(TryFinally* a) { 373 void CodeGenerator::VisitTryFinally(TryFinally* a) {
366 UNIMPLEMENTED(); 374 UNIMPLEMENTED();
367 } 375 }
368 376
369 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* a) { 377 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* a) {
370 UNIMPLEMENTED(); 378 UNIMPLEMENTED();
371 } 379 }
372 380
373 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* a) { 381
374 UNIMPLEMENTED(); 382 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
383 // Call the runtime to instantiate the function boilerplate object.
384 // The inevitable call will sync frame elements to memory anyway, so
385 // we do it eagerly to allow us to push the arguments directly into
386 // place.
387 ASSERT(boilerplate->IsBoilerplate());
388 frame_->SyncRange(0, frame_->element_count() - 1);
389
390 // Push the boilerplate on the stack.
391 __ movq(kScratchRegister, boilerplate, RelocInfo::EMBEDDED_OBJECT);
392 frame_->EmitPush(kScratchRegister);
393
394 // Create a new closure.
395 frame_->EmitPush(rsi);
396 Result result = frame_->CallRuntime(Runtime::kNewClosure, 2);
397 frame_->Push(&result);
375 } 398 }
376 399
400
401 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
402 Comment cmnt(masm_, "[ FunctionLiteral");
403
404 // Build the function boilerplate and instantiate it.
405 Handle<JSFunction> boilerplate = BuildBoilerplate(node);
406 // Check for stack-overflow exception.
407 if (HasStackOverflow()) return;
408 InstantiateBoilerplate(boilerplate);
409 }
410
411
377 void CodeGenerator::VisitFunctionBoilerplateLiteral( 412 void CodeGenerator::VisitFunctionBoilerplateLiteral(
378 FunctionBoilerplateLiteral* a) { 413 FunctionBoilerplateLiteral* node) {
379 UNIMPLEMENTED(); 414 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
415 InstantiateBoilerplate(node->boilerplate());
380 } 416 }
381 417
418
382 void CodeGenerator::VisitConditional(Conditional* a) { 419 void CodeGenerator::VisitConditional(Conditional* a) {
383 UNIMPLEMENTED(); 420 UNIMPLEMENTED();
384 } 421 }
385 422
386 void CodeGenerator::VisitSlot(Slot* node) { 423 void CodeGenerator::VisitSlot(Slot* node) {
387 Comment cmnt(masm_, "[ Slot"); 424 Comment cmnt(masm_, "[ Slot");
388 LoadFromSlot(node, typeof_state()); 425 LoadFromSlot(node, typeof_state());
389 } 426 }
390 427
391 428
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 551
515 552
516 void CodeGenerator::VisitThrow(Throw* a) { 553 void CodeGenerator::VisitThrow(Throw* a) {
517 // UNIMPLEMENTED(); 554 // UNIMPLEMENTED();
518 } 555 }
519 556
520 void CodeGenerator::VisitProperty(Property* a) { 557 void CodeGenerator::VisitProperty(Property* a) {
521 UNIMPLEMENTED(); 558 UNIMPLEMENTED();
522 } 559 }
523 560
524 void CodeGenerator::VisitCall(Call* a) { 561
525 UNIMPLEMENTED(); 562 void CodeGenerator::VisitCall(Call* node) {
563 Comment cmnt(masm_, "[ Call");
564
565 ZoneList<Expression*>* args = node->arguments();
566
567 CodeForStatementPosition(node);
568
569 // Check if the function is a variable or a property.
570 Expression* function = node->expression();
571 Variable* var = function->AsVariableProxy()->AsVariable();
572 Property* property = function->AsProperty();
573
574 // ------------------------------------------------------------------------
575 // Fast-case: Use inline caching.
576 // ---
577 // According to ECMA-262, section 11.2.3, page 44, the function to call
578 // must be resolved after the arguments have been evaluated. The IC code
579 // automatically handles this by loading the arguments before the function
580 // is resolved in cache misses (this also holds for megamorphic calls).
581 // ------------------------------------------------------------------------
582
583 if (var != NULL && !var->is_this() && var->is_global()) {
584 // ----------------------------------
585 // JavaScript example: 'foo(1, 2, 3)' // foo is global
586 // ----------------------------------
587
588 // Push the name of the function and the receiver onto the stack.
589 frame_->Push(var->name());
590
591 // Pass the global object as the receiver and let the IC stub
592 // patch the stack to use the global proxy as 'this' in the
593 // invoked function.
594 LoadGlobal();
595
596 // Load the arguments.
597 int arg_count = args->length();
598 for (int i = 0; i < arg_count; i++) {
599 Load(args->at(i));
600 }
601
602 // Call the IC initialization code.
603 CodeForSourcePosition(node->position());
604 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT,
605 arg_count,
606 loop_nesting());
607 frame_->RestoreContextRegister();
608 // Replace the function on the stack with the result.
609 frame_->SetElementAt(0, &result);
610 } else if (var != NULL && var->slot() != NULL &&
611 var->slot()->type() == Slot::LOOKUP) {
612 // TODO(X64): Enable calls of non-global functions.
613 UNIMPLEMENTED();
614 /*
615 // ----------------------------------
616 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj
617 // ----------------------------------
618
619 // Load the function from the context. Sync the frame so we can
620 // push the arguments directly into place.
621 frame_->SyncRange(0, frame_->element_count() - 1);
622 frame_->EmitPush(esi);
623 frame_->EmitPush(Immediate(var->name()));
624 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
625 // The runtime call returns a pair of values in eax and edx. The
626 // looked-up function is in eax and the receiver is in edx. These
627 // register references are not ref counted here. We spill them
628 // eagerly since they are arguments to an inevitable call (and are
629 // not sharable by the arguments).
630 ASSERT(!allocator()->is_used(eax));
631 frame_->EmitPush(eax);
632
633 // Load the receiver.
634 ASSERT(!allocator()->is_used(edx));
635 frame_->EmitPush(edx);
636
637 // Call the function.
638 CallWithArguments(args, node->position());
639 */
640 } else if (property != NULL) {
641 UNIMPLEMENTED();
642 /*
643 // Check if the key is a literal string.
644 Literal* literal = property->key()->AsLiteral();
645
646 if (literal != NULL && literal->handle()->IsSymbol()) {
647 // ------------------------------------------------------------------
648 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
649 // ------------------------------------------------------------------
650
651 // Push the name of the function and the receiver onto the stack.
652 frame_->Push(literal->handle());
653 Load(property->obj());
654
655 // Load the arguments.
656 int arg_count = args->length();
657 for (int i = 0; i < arg_count; i++) {
658 Load(args->at(i));
659 }
660
661 // Call the IC initialization code.
662 CodeForSourcePosition(node->position());
663 Result result =
664 frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, loop_nesting());
665 frame_->RestoreContextRegister();
666 // Replace the function on the stack with the result.
667 frame_->SetElementAt(0, &result);
668
669 } else {
670 // -------------------------------------------
671 // JavaScript example: 'array[index](1, 2, 3)'
672 // -------------------------------------------
673
674 // Load the function to call from the property through a reference.
675 Reference ref(this, property);
676 ref.GetValue(NOT_INSIDE_TYPEOF);
677
678 // Pass receiver to called function.
679 if (property->is_synthetic()) {
680 // Use global object as receiver.
681 LoadGlobalReceiver();
682 } else {
683 // The reference's size is non-negative.
684 frame_->PushElementAt(ref.size());
685 }
686
687 // Call the function.
688 CallWithArguments(args, node->position());
689 }
690 */
691 } else {
692 // ----------------------------------
693 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
694 // ----------------------------------
695
696 // Load the function.
697 Load(function);
698
699 // Pass the global proxy as the receiver.
700 LoadGlobalReceiver();
701
702 // Call the function.
703 CallWithArguments(args, node->position());
704 }
526 } 705 }
527 706
707
528 void CodeGenerator::VisitCallEval(CallEval* a) { 708 void CodeGenerator::VisitCallEval(CallEval* a) {
529 UNIMPLEMENTED(); 709 UNIMPLEMENTED();
530 } 710 }
531 711
532 void CodeGenerator::VisitCallNew(CallNew* a) { 712 void CodeGenerator::VisitCallNew(CallNew* a) {
533 UNIMPLEMENTED(); 713 UNIMPLEMENTED();
534 } 714 }
535 715
536 void CodeGenerator::VisitCallRuntime(CallRuntime* a) { 716 void CodeGenerator::VisitCallRuntime(CallRuntime* a) {
537 UNIMPLEMENTED(); 717 UNIMPLEMENTED();
538 } 718 }
539 719
720
540 void CodeGenerator::VisitUnaryOperation(UnaryOperation* a) { 721 void CodeGenerator::VisitUnaryOperation(UnaryOperation* a) {
541 UNIMPLEMENTED(); 722 UNIMPLEMENTED();
542 } 723 }
543 724
544 void CodeGenerator::VisitCountOperation(CountOperation* a) { 725 void CodeGenerator::VisitCountOperation(CountOperation* a) {
545 UNIMPLEMENTED(); 726 UNIMPLEMENTED();
546 } 727 }
547 728
548 void CodeGenerator::VisitBinaryOperation(BinaryOperation* a) { 729 void CodeGenerator::VisitBinaryOperation(BinaryOperation* a) {
549 UNIMPLEMENTED(); 730 UNIMPLEMENTED();
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 void CodeGenerator::LoadGlobal() { 1390 void CodeGenerator::LoadGlobal() {
1210 if (in_spilled_code()) { 1391 if (in_spilled_code()) {
1211 frame_->EmitPush(GlobalObject()); 1392 frame_->EmitPush(GlobalObject());
1212 } else { 1393 } else {
1213 Result temp = allocator_->Allocate(); 1394 Result temp = allocator_->Allocate();
1214 __ movq(temp.reg(), GlobalObject()); 1395 __ movq(temp.reg(), GlobalObject());
1215 frame_->Push(&temp); 1396 frame_->Push(&temp);
1216 } 1397 }
1217 } 1398 }
1218 1399
1400
1401 void CodeGenerator::LoadGlobalReceiver() {
1402 Result temp = allocator_->Allocate();
1403 Register reg = temp.reg();
1404 __ movq(reg, GlobalObject());
1405 __ movq(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset));
1406 frame_->Push(&temp);
1407 }
1408
1409
1219 #undef __ 1410 #undef __
1220 1411
1221 // End of CodeGenerator implementation. 1412 // End of CodeGenerator implementation.
1222 1413
1223 // ----------------------------------------------------------------------------- 1414 // -----------------------------------------------------------------------------
1224 // Implementation of stubs. 1415 // Implementation of stubs.
1225 1416
1226 // Stub classes have public member named masm, not masm_. 1417 // Stub classes have public member named masm, not masm_.
1227 #define __ ACCESS_MASM(masm) 1418 #define __ ACCESS_MASM(masm)
1228 1419
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1581 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } 1772 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
1582 #endif 1773 #endif
1583 1774
1584 Major MajorKey() { return CallFunction; } 1775 Major MajorKey() { return CallFunction; }
1585 int MinorKey() { return argc_; } 1776 int MinorKey() { return argc_; }
1586 InLoopFlag InLoop() { return in_loop_; } 1777 InLoopFlag InLoop() { return in_loop_; }
1587 }; 1778 };
1588 1779
1589 1780
1590 void CallFunctionStub::Generate(MacroAssembler* masm) { 1781 void CallFunctionStub::Generate(MacroAssembler* masm) {
1782 Label slow;
1783
1784 // Get the function to call from the stack.
1785 // +2 ~ receiver, return address
1786 __ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize));
1787
1788 // Check that the function really is a JavaScript function.
1789 __ testq(rdi, Immediate(kSmiTagMask));
1790 __ j(zero, &slow);
1791 // Goto slow case if we do not have a function.
1792 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
1793 __ j(not_equal, &slow);
1794
1795 // Fast-case: Just invoke the function.
1796 ParameterCount actual(argc_);
1797 __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
1798
1799 // Slow-case: Non-function called.
1800 __ bind(&slow);
1801 __ Set(rax, argc_);
1802 __ Set(rbx, 0);
1803 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
1804 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
1805 __ Jump(adaptor, RelocInfo::CODE_TARGET);
1806 }
1807
1808
1809 // Call the function just below TOS on the stack with the given
1810 // arguments. The receiver is the TOS.
1811 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
1812 int position) {
1813 // Push the arguments ("left-to-right") on the stack.
1814 int arg_count = args->length();
1815 for (int i = 0; i < arg_count; i++) {
1816 Load(args->at(i));
1817 }
1818
1819 // Record the position for debugging purposes.
1820 CodeForSourcePosition(position);
1821
1822 // Use the shared code stub to call the function.
1823 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
1824 CallFunctionStub call_function(arg_count, in_loop);
1825 Result answer = frame_->CallStub(&call_function, arg_count + 1);
1826 // Restore context and replace function on the stack with the
1827 // result of the stub invocation.
1828 frame_->RestoreContextRegister();
1829 frame_->SetElementAt(0, &answer);
1591 } 1830 }
1592 1831
1593 1832
1594 void InstanceofStub::Generate(MacroAssembler* masm) { 1833 void InstanceofStub::Generate(MacroAssembler* masm) {
1595 } 1834 }
1596 1835
1597 1836
1598
1599 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { 1837 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
1600 // The displacement is used for skipping the return address and the 1838 // The displacement is used for skipping the return address and the
1601 // frame pointer on the stack. It is the offset of the last 1839 // frame pointer on the stack. It is the offset of the last
1602 // parameter (if any) relative to the frame pointer. 1840 // parameter (if any) relative to the frame pointer.
1603 static const int kDisplacement = 2 * kPointerSize; 1841 static const int kDisplacement = 2 * kPointerSize;
1604 1842
1605 // Check if the calling frame is an arguments adaptor frame. 1843 // Check if the calling frame is an arguments adaptor frame.
1606 Label runtime; 1844 Label runtime;
1607 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 1845 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
1608 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 1846 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
2044 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers 2282 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers
2045 2283
2046 // Restore frame pointer and return. 2284 // Restore frame pointer and return.
2047 __ pop(rbp); 2285 __ pop(rbp);
2048 __ ret(0); 2286 __ ret(0);
2049 } 2287 }
2050 2288
2051 #undef __ 2289 #undef __
2052 2290
2053 } } // namespace v8::internal 2291 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698