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

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

Issue 340037: Support for calls on named and keyed properties of the form:... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 1 month 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/x64/codegen-x64.cc ('k') | test/mjsunit/compiler/function-call.js » ('j') | 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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 } 84 }
85 85
86 { Comment cmnt(masm_, "[ Body"); 86 { Comment cmnt(masm_, "[ Body");
87 VisitStatements(fun->body()); 87 VisitStatements(fun->body());
88 } 88 }
89 89
90 { Comment cmnt(masm_, "[ return <undefined>;"); 90 { Comment cmnt(masm_, "[ return <undefined>;");
91 // Emit a 'return undefined' in case control fell off the end of the 91 // Emit a 'return undefined' in case control fell off the end of the
92 // body. 92 // body.
93 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 93 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
94 }
95 { Comment cmnt(masm_, "Return sequence");
94 SetReturnPosition(fun); 96 SetReturnPosition(fun);
95 if (FLAG_trace) { 97
96 __ push(rax); 98 if (return_label_.is_bound()) {
97 __ CallRuntime(Runtime::kTraceExit, 1); 99 __ jmp(&return_label_);
100 } else {
101 __ bind(&return_label_);
102
103 if (FLAG_trace) {
104 __ push(rax);
105 __ CallRuntime(Runtime::kTraceExit, 1);
106 }
107 __ RecordJSReturn();
108
109 // Do not use the leave instruction here because it is too short to
110 // patch with the code required by the debugger.
111 __ movq(rsp, rbp);
112 __ pop(rbp);
113 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
114 #ifdef ENABLE_DEBUGGER_SUPPORT
115 // Add padding that will be overwritten by a debugger breakpoint. We
116 // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
117 // (3 + 1 + 3).
118 const int kPadding = Debug::kX64JSReturnSequenceLength - 7;
119 for (int i = 0; i < kPadding; ++i) {
120 masm_->int3();
121 }
122 #endif
98 } 123 }
99 __ RecordJSReturn();
100
101 // Do not use the leave instruction here because it is too short to
102 // patch with the code required by the debugger.
103 __ movq(rsp, rbp);
104 __ pop(rbp);
105 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
106 #ifdef ENABLE_DEBUGGER_SUPPORT
107 // Add padding that will be overwritten by a debugger breakpoint. We
108 // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
109 // (3 + 1 + 3).
110 const int kPadding = Debug::kX64JSReturnSequenceLength - 7;
111 for (int i = 0; i < kPadding; ++i) {
112 masm_->int3();
113 }
114 #endif
115 } 124 }
116 } 125 }
117 126
118 127
119 void FastCodeGenerator::Move(Expression::Context context, Slot* source) { 128 void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
120 switch (context) { 129 switch (context) {
121 case Expression::kUninitialized: 130 case Expression::kUninitialized:
122 UNREACHABLE(); 131 UNREACHABLE();
123 case Expression::kEffect: 132 case Expression::kEffect:
124 break; 133 break;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 SetStatementPosition(stmt); 181 SetStatementPosition(stmt);
173 Expression* expr = stmt->expression(); 182 Expression* expr = stmt->expression();
174 if (expr->AsLiteral() != NULL) { 183 if (expr->AsLiteral() != NULL) {
175 __ Move(rax, expr->AsLiteral()->handle()); 184 __ Move(rax, expr->AsLiteral()->handle());
176 } else { 185 } else {
177 Visit(expr); 186 Visit(expr);
178 ASSERT_EQ(Expression::kValue, expr->context()); 187 ASSERT_EQ(Expression::kValue, expr->context());
179 __ pop(rax); 188 __ pop(rax);
180 } 189 }
181 190
182 if (FLAG_trace) { 191 if (return_label_.is_bound()) {
183 __ push(rax); 192 __ jmp(&return_label_);
184 __ CallRuntime(Runtime::kTraceExit, 1); 193 } else {
194 __ bind(&return_label_);
195
196 if (FLAG_trace) {
197 __ push(rax);
198 __ CallRuntime(Runtime::kTraceExit, 1);
199 }
200
201 __ RecordJSReturn();
202 // Do not use the leave instruction here because it is too short to
203 // patch with the code required by the debugger.
204 __ movq(rsp, rbp);
205 __ pop(rbp);
206 __ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
207 #ifdef ENABLE_DEBUGGER_SUPPORT
208 // Add padding that will be overwritten by a debugger breakpoint. We
209 // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
210 // (3 + 1 + 3).
211 const int kPadding = Debug::kX64JSReturnSequenceLength - 7;
212 for (int i = 0; i < kPadding; ++i) {
213 masm_->int3();
214 }
215 #endif
185 } 216 }
186
187 __ RecordJSReturn();
188 // Do not use the leave instruction here because it is too short to
189 // patch with the code required by the debugger.
190 __ movq(rsp, rbp);
191 __ pop(rbp);
192 __ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
193 #ifdef ENABLE_DEBUGGER_SUPPORT
194 // Add padding that will be overwritten by a debugger breakpoint. We
195 // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
196 // (3 + 1 + 3).
197 const int kPadding = Debug::kX64JSReturnSequenceLength - 7;
198 for (int i = 0; i < kPadding; ++i) {
199 masm_->int3();
200 }
201 #endif
202 } 217 }
203 218
204 219
205 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 220 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
206 Comment cmnt(masm_, "[ FunctionLiteral"); 221 Comment cmnt(masm_, "[ FunctionLiteral");
207 222
208 // Build the function boilerplate and instantiate it. 223 // Build the function boilerplate and instantiate it.
209 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); 224 Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
210 if (HasStackOverflow()) return; 225 if (HasStackOverflow()) return;
211 226
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 // on the stack. 503 // on the stack.
489 504
490 // Code for the right-hand-side expression depends on its type. 505 // Code for the right-hand-side expression depends on its type.
491 if (rhs->AsLiteral() != NULL) { 506 if (rhs->AsLiteral() != NULL) {
492 __ Move(rax, rhs->AsLiteral()->handle()); 507 __ Move(rax, rhs->AsLiteral()->handle());
493 } else { 508 } else {
494 ASSERT_EQ(Expression::kValue, rhs->context()); 509 ASSERT_EQ(Expression::kValue, rhs->context());
495 Visit(rhs); 510 Visit(rhs);
496 __ pop(rax); 511 __ pop(rax);
497 } 512 }
513 // Record position for debugger.
514 SetSourcePosition(expr->position());
498 __ Move(rcx, var->name()); 515 __ Move(rcx, var->name());
499 __ push(CodeGenerator::GlobalObject()); 516 __ push(CodeGenerator::GlobalObject());
500 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 517 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
501 __ Call(ic, RelocInfo::CODE_TARGET); 518 __ Call(ic, RelocInfo::CODE_TARGET);
502 // Overwrite the global object on the stack with the result if needed. 519 // Overwrite the global object on the stack with the result if needed.
503 DropAndMove(expr->context(), rax); 520 DropAndMove(expr->context(), rax);
504 } else { 521 } else {
505 // Local or parameter assignment. 522 // Local or parameter assignment.
506 523
507 // Code for the right-hand-side expression depends on its type. 524 // Code for the right-hand-side expression depends on its type.
(...skipping 29 matching lines...) Expand all
537 Comment cmnt(masm_, "[ Property"); 554 Comment cmnt(masm_, "[ Property");
538 Expression* key = expr->key(); 555 Expression* key = expr->key();
539 uint32_t dummy; 556 uint32_t dummy;
540 557
541 // Record the source position for the property load. 558 // Record the source position for the property load.
542 SetSourcePosition(expr->position()); 559 SetSourcePosition(expr->position());
543 560
544 // Evaluate receiver. 561 // Evaluate receiver.
545 Visit(expr->obj()); 562 Visit(expr->obj());
546 563
564
547 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && 565 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() &&
548 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { 566 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) {
549 // Do a NAMED property load. 567 // Do a NAMED property load.
550 // The IC expects the property name in rcx and the receiver on the stack. 568 // The IC expects the property name in rcx and the receiver on the stack.
551 __ Move(rcx, key->AsLiteral()->handle()); 569 __ Move(rcx, key->AsLiteral()->handle());
552 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 570 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
553 __ call(ic, RelocInfo::CODE_TARGET); 571 __ call(ic, RelocInfo::CODE_TARGET);
554 // By emitting a nop we make sure that we do not have a "test rax,..." 572 // By emitting a nop we make sure that we do not have a "test rax,..."
555 // instruction after the call it is treated specially by the LoadIC code. 573 // instruction after the call it is treated specially by the LoadIC code.
556 __ nop(); 574 __ nop();
557 } else { 575 } else {
558 // Do a KEYED property load. 576 // Do a KEYED property load.
559 Visit(expr->key()); 577 Visit(expr->key());
560 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 578 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
561 __ call(ic, RelocInfo::CODE_TARGET); 579 __ call(ic, RelocInfo::CODE_TARGET);
562 // By emitting a nop we make sure that we do not have a "test rax,..." 580 // By emitting a nop we make sure that we do not have a "test rax,..."
563 // instruction after the call it is treated specially by the LoadIC code. 581 // instruction after the call it is treated specially by the LoadIC code.
564 __ nop(); 582 __ nop();
565 // Drop key left on the stack by IC. 583 // Drop key left on the stack by IC.
566 __ addq(rsp, Immediate(kPointerSize)); 584 __ addq(rsp, Immediate(kPointerSize));
567 } 585 }
568 DropAndMove(expr->context(), rax); 586 DropAndMove(expr->context(), rax);
569 } 587 }
570 588
571 589
572 void FastCodeGenerator::VisitCall(Call* expr) { 590 void FastCodeGenerator::EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info) {
573 Expression* fun = expr->expression(); 591 // Code common for calls using the IC.
574 ZoneList<Expression*>* args = expr->arguments(); 592 ZoneList<Expression*>* args = expr->arguments();
575 Variable* var = fun->AsVariableProxy()->AsVariable();
576 ASSERT(var != NULL && !var->is_this() && var->is_global());
577 ASSERT(!var->is_possibly_eval());
578
579 __ Push(var->name());
580 // Push global object (receiver).
581 __ push(CodeGenerator::GlobalObject());
582 int arg_count = args->length(); 593 int arg_count = args->length();
583 for (int i = 0; i < arg_count; i++) { 594 for (int i = 0; i < arg_count; i++) {
584 Visit(args->at(i)); 595 Visit(args->at(i));
585 ASSERT_EQ(Expression::kValue, args->at(i)->context()); 596 ASSERT_EQ(Expression::kValue, args->at(i)->context());
586 } 597 }
587 // Record source position for debugger 598 // Record source position for debugger.
588 SetSourcePosition(expr->position()); 599 SetSourcePosition(expr->position());
589 // Call the IC initialization code. 600 // Call the IC initialization code.
590 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 601 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
591 NOT_IN_LOOP); 602 NOT_IN_LOOP);
592 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 603 __ call(ic, reloc_info);
593 // Restore context register. 604 // Restore context register.
594 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 605 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
595 // Discard the function left on TOS. 606 // Discard the function left on TOS.
596 DropAndMove(expr->context(), rax); 607 DropAndMove(expr->context(), rax);
597 } 608 }
598 609
599 610
611 void FastCodeGenerator::EmitCallWithStub(Call* expr) {
612 // Code common for calls using the call stub.
613 ZoneList<Expression*>* args = expr->arguments();
614 int arg_count = args->length();
615 for (int i = 0; i < arg_count; i++) {
616 Visit(args->at(i));
617 }
618 // Record source position for debugger.
619 SetSourcePosition(expr->position());
620 CallFunctionStub stub(arg_count, NOT_IN_LOOP);
621 __ CallStub(&stub);
622 // Restore context register.
623 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
624 // Discard the function left on TOS.
625 DropAndMove(expr->context(), rax);
626 }
627
628
629 void FastCodeGenerator::VisitCall(Call* expr) {
630 Expression* fun = expr->expression();
631
632 if (fun->AsProperty() != NULL) {
633 // Call on a property.
634 Property* prop = fun->AsProperty();
635 Literal* key = prop->key()->AsLiteral();
636 if (key != NULL && key->handle()->IsSymbol()) {
637 // Call on a named property: foo.x(1,2,3)
638 __ Push(key->handle());
639 Visit(prop->obj());
640 // Use call IC
641 EmitCallWithIC(expr, RelocInfo::CODE_TARGET);
642 } else {
643 // Call on a keyed property: foo[key](1,2,3)
644 // Use a keyed load IC followed by a call IC.
645 Visit(prop->obj());
646 Visit(prop->key());
647 // Record source position of property.
648 SetSourcePosition(prop->position());
649 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
650 __ call(ic, RelocInfo::CODE_TARGET);
651 // By emitting a nop we make sure that we do not have a "test eax,..."
652 // instruction after the call it is treated specially by the LoadIC code.
653 __ nop();
654 // Drop key left on the stack by IC.
655 __ addq(rsp, Immediate(kPointerSize));
656 // Pop receiver.
657 __ pop(rbx);
658 // Push result (function).
659 __ push(rax);
660 // Push receiver object on stack.
661 if (prop->is_synthetic()) {
662 __ push(CodeGenerator::GlobalObject());
663 } else {
664 __ push(rbx);
665 }
666 EmitCallWithStub(expr);
667 }
668 } else if (fun->AsVariableProxy()->AsVariable() != NULL) {
669 // Call on a global variable
670 Variable* var = fun->AsVariableProxy()->AsVariable();
671 ASSERT(var != NULL && !var->is_this() && var->is_global());
672 ASSERT(!var->is_possibly_eval());
673 __ Push(var->name());
674 // Push global object (receiver).
675 __ push(CodeGenerator::GlobalObject());
676 EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
677 } else {
678 // Calls we cannot handle right now.
679 // Should bailout in the CodeGenSelector.
680 UNREACHABLE();
681 }
682 }
683
684
600 void FastCodeGenerator::VisitCallNew(CallNew* expr) { 685 void FastCodeGenerator::VisitCallNew(CallNew* expr) {
601 Comment cmnt(masm_, "[ CallNew"); 686 Comment cmnt(masm_, "[ CallNew");
602 // According to ECMA-262, section 11.2.2, page 44, the function 687 // According to ECMA-262, section 11.2.2, page 44, the function
603 // expression in new calls must be evaluated before the 688 // expression in new calls must be evaluated before the
604 // arguments. 689 // arguments.
605 // Push function on the stack. 690 // Push function on the stack.
606 Visit(expr->expression()); 691 Visit(expr->expression());
607 ASSERT_EQ(Expression::kValue, expr->expression()->context()); 692 ASSERT_EQ(Expression::kValue, expr->expression()->context());
608 // If location is value, already on the stack, 693 // If location is value, already on the stack,
609 694
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
783 } 868 }
784 // Save or discard the right-hand value as needed. 869 // Save or discard the right-hand value as needed.
785 Visit(right); 870 Visit(right);
786 ASSERT_EQ(context, right->context()); 871 ASSERT_EQ(context, right->context());
787 872
788 __ bind(&done); 873 __ bind(&done);
789 } 874 }
790 875
791 876
792 } } // namespace v8::internal 877 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.cc ('k') | test/mjsunit/compiler/function-call.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698