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

Side by Side Diff: src/ia32/fast-codegen-ia32.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/ia32/codegen-ia32.cc ('k') | src/x64/codegen-x64.h » ('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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 __ push(esi); // Callee's context. 58 __ push(esi); // Callee's context.
59 __ push(edi); // Callee's JS Function. 59 __ push(edi); // Callee's JS Function.
60 60
61 { Comment cmnt(masm_, "[ Allocate locals"); 61 { Comment cmnt(masm_, "[ Allocate locals");
62 int locals_count = fun->scope()->num_stack_slots(); 62 int locals_count = fun->scope()->num_stack_slots();
63 for (int i = 0; i < locals_count; i++) { 63 for (int i = 0; i < locals_count; i++) {
64 __ push(Immediate(Factory::undefined_value())); 64 __ push(Immediate(Factory::undefined_value()));
65 } 65 }
66 } 66 }
67 67
68 { Comment cmnt(masm_, "[ Declarations");
69 VisitDeclarations(fun->scope()->declarations());
70 }
71
68 { Comment cmnt(masm_, "[ Stack check"); 72 { Comment cmnt(masm_, "[ Stack check");
69 Label ok; 73 Label ok;
70 ExternalReference stack_guard_limit = 74 ExternalReference stack_guard_limit =
71 ExternalReference::address_of_stack_guard_limit(); 75 ExternalReference::address_of_stack_guard_limit();
72 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); 76 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
73 __ j(above_equal, &ok, taken); 77 __ j(above_equal, &ok, taken);
74 StackCheckStub stub; 78 StackCheckStub stub;
75 __ CallStub(&stub); 79 __ CallStub(&stub);
76 __ bind(&ok); 80 __ bind(&ok);
77 } 81 }
78 82
79 { Comment cmnt(masm_, "[ Declarations");
80 VisitDeclarations(fun->scope()->declarations());
81 }
82
83 if (FLAG_trace) { 83 if (FLAG_trace) {
84 __ CallRuntime(Runtime::kTraceEnter, 0); 84 __ CallRuntime(Runtime::kTraceEnter, 0);
85 } 85 }
86 86
87 { Comment cmnt(masm_, "[ Body"); 87 { Comment cmnt(masm_, "[ Body");
88 VisitStatements(fun->body()); 88 VisitStatements(fun->body());
89 } 89 }
90 90
91 { Comment cmnt(masm_, "[ return <undefined>;"); 91 { Comment cmnt(masm_, "[ return <undefined>;");
92 // Emit a 'return undefined' in case control fell off the end of the 92 // Emit a 'return undefined' in case control fell off the end of the
93 // body. 93 // body.
94 __ mov(eax, Factory::undefined_value()); 94 __ mov(eax, Factory::undefined_value());
95 }
96 { Comment cmnt(masm_, "[ Return sequence");
95 SetReturnPosition(fun); 97 SetReturnPosition(fun);
96 98
97 if (FLAG_trace) { 99 if (return_label_.is_bound()) {
98 __ push(eax); 100 __ jmp(&return_label_);
99 __ CallRuntime(Runtime::kTraceExit, 1); 101 } else {
102 // Common return label
103 __ bind(&return_label_);
104
105 if (FLAG_trace) {
106 __ push(eax);
107 __ CallRuntime(Runtime::kTraceExit, 1);
108 }
109 __ RecordJSReturn();
110 // Do not use the leave instruction here because it is too short to
111 // patch with the code required by the debugger.
112 __ mov(esp, ebp);
113 __ pop(ebp);
114 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
100 } 115 }
101 __ RecordJSReturn();
102 // Do not use the leave instruction here because it is too short to
103 // patch with the code required by the debugger.
104 __ mov(esp, ebp);
105 __ pop(ebp);
106 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
107 } 116 }
108 } 117 }
109 118
110 119
111 void FastCodeGenerator::Move(Expression::Context context, Slot* source) { 120 void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
112 switch (context) { 121 switch (context) {
113 case Expression::kUninitialized: 122 case Expression::kUninitialized:
114 UNREACHABLE(); 123 UNREACHABLE();
115 case Expression::kEffect: 124 case Expression::kEffect:
116 break; 125 break;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 SetStatementPosition(stmt); 173 SetStatementPosition(stmt);
165 Expression* expr = stmt->expression(); 174 Expression* expr = stmt->expression();
166 if (expr->AsLiteral() != NULL) { 175 if (expr->AsLiteral() != NULL) {
167 __ mov(eax, expr->AsLiteral()->handle()); 176 __ mov(eax, expr->AsLiteral()->handle());
168 } else { 177 } else {
169 ASSERT_EQ(Expression::kValue, expr->context()); 178 ASSERT_EQ(Expression::kValue, expr->context());
170 Visit(expr); 179 Visit(expr);
171 __ pop(eax); 180 __ pop(eax);
172 } 181 }
173 182
174 if (FLAG_trace) { 183 if (return_label_.is_bound()) {
175 __ push(eax); 184 __ jmp(&return_label_);
176 __ CallRuntime(Runtime::kTraceExit, 1); 185 } else {
186 __ bind(&return_label_);
187
188 if (FLAG_trace) {
189 __ push(eax);
190 __ CallRuntime(Runtime::kTraceExit, 1);
191 }
192
193 __ RecordJSReturn();
194
195 // Do not use the leave instruction here because it is too short to
196 // patch with the code required by the debugger.
197 __ mov(esp, ebp);
198 __ pop(ebp);
199 __ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
177 } 200 }
178 __ RecordJSReturn();
179
180 // Do not use the leave instruction here because it is too short to
181 // patch with the code required by the debugger.
182 __ mov(esp, ebp);
183 __ pop(ebp);
184 __ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
185 } 201 }
186 202
187 203
188 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 204 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
189 Comment cmnt(masm_, "[ FunctionLiteral"); 205 Comment cmnt(masm_, "[ FunctionLiteral");
190 206
191 // Build the function boilerplate and instantiate it. 207 // Build the function boilerplate and instantiate it.
192 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); 208 Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
193 if (HasStackOverflow()) return; 209 if (HasStackOverflow()) return;
194 210
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 // on the stack. 493 // on the stack.
478 494
479 // Code for the right-hand-side expression depends on its type. 495 // Code for the right-hand-side expression depends on its type.
480 if (rhs->AsLiteral() != NULL) { 496 if (rhs->AsLiteral() != NULL) {
481 __ mov(eax, rhs->AsLiteral()->handle()); 497 __ mov(eax, rhs->AsLiteral()->handle());
482 } else { 498 } else {
483 ASSERT_EQ(Expression::kValue, rhs->context()); 499 ASSERT_EQ(Expression::kValue, rhs->context());
484 Visit(rhs); 500 Visit(rhs);
485 __ pop(eax); 501 __ pop(eax);
486 } 502 }
503 // Record position for debugger.
504 SetSourcePosition(expr->position());
487 __ mov(ecx, var->name()); 505 __ mov(ecx, var->name());
488 __ push(CodeGenerator::GlobalObject()); 506 __ push(CodeGenerator::GlobalObject());
489 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 507 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
490 __ call(ic, RelocInfo::CODE_TARGET); 508 __ call(ic, RelocInfo::CODE_TARGET);
491 // Overwrite the global object on the stack with the result if needed. 509 // Overwrite the global object on the stack with the result if needed.
492 DropAndMove(expr->context(), eax); 510 DropAndMove(expr->context(), eax);
493 } else { 511 } else {
494 // Local or parameter assignment. 512 // Local or parameter assignment.
495 ASSERT(var->slot() != NULL); 513 ASSERT(var->slot() != NULL);
496 514
(...skipping 29 matching lines...) Expand all
526 void FastCodeGenerator::VisitProperty(Property* expr) { 544 void FastCodeGenerator::VisitProperty(Property* expr) {
527 Comment cmnt(masm_, "[ Property"); 545 Comment cmnt(masm_, "[ Property");
528 Expression* key = expr->key(); 546 Expression* key = expr->key();
529 uint32_t dummy; 547 uint32_t dummy;
530 548
531 // Record the source position for the property load. 549 // Record the source position for the property load.
532 SetSourcePosition(expr->position()); 550 SetSourcePosition(expr->position());
533 551
534 // Evaluate receiver. 552 // Evaluate receiver.
535 Visit(expr->obj()); 553 Visit(expr->obj());
554
536 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && 555 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() &&
537 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { 556 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) {
538 // Do a NAMED property load. 557 // Do a NAMED property load.
539 // The IC expects the property name in ecx and the receiver on the stack. 558 // The IC expects the property name in ecx and the receiver on the stack.
540 __ mov(ecx, Immediate(key->AsLiteral()->handle())); 559 __ mov(ecx, Immediate(key->AsLiteral()->handle()));
541 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 560 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
542 __ call(ic, RelocInfo::CODE_TARGET); 561 __ call(ic, RelocInfo::CODE_TARGET);
543 // By emitting a nop we make sure that we do not have a test eax 562 // By emitting a nop we make sure that we do not have a test eax
544 // instruction after the call it is treated specially by the LoadIC code. 563 // instruction after the call it is treated specially by the LoadIC code.
545 __ nop(); 564 __ nop();
546 } else { 565 } else {
547 // Do a KEYED property load. 566 // Do a KEYED property load.
548 Visit(expr->key()); 567 Visit(expr->key());
549 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 568 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
550 __ call(ic, RelocInfo::CODE_TARGET); 569 __ call(ic, RelocInfo::CODE_TARGET);
551 // By emitting a nop we make sure that we do not have a "test eax,..." 570 // By emitting a nop we make sure that we do not have a "test eax,..."
552 // instruction after the call it is treated specially by the LoadIC code. 571 // instruction after the call it is treated specially by the LoadIC code.
553 __ nop(); 572 __ nop();
554 // Drop key left on the stack by IC. 573 // Drop key left on the stack by IC.
555 __ add(Operand(esp), Immediate(kPointerSize)); 574 __ add(Operand(esp), Immediate(kPointerSize));
556 } 575 }
557 DropAndMove(expr->context(), eax); 576 DropAndMove(expr->context(), eax);
558 } 577 }
559 578
560 579
561 void FastCodeGenerator::VisitCall(Call* expr) { 580 void FastCodeGenerator::EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info) {
562 Expression* fun = expr->expression(); 581 // Code common for calls using the IC.
563 ZoneList<Expression*>* args = expr->arguments(); 582 ZoneList<Expression*>* args = expr->arguments();
564 Variable* var = fun->AsVariableProxy()->AsVariable();
565 ASSERT(var != NULL && !var->is_this() && var->is_global());
566 ASSERT(!var->is_possibly_eval());
567
568 __ push(Immediate(var->name()));
569 // Push global object (receiver).
570 __ push(CodeGenerator::GlobalObject());
571 int arg_count = args->length(); 583 int arg_count = args->length();
572 for (int i = 0; i < arg_count; i++) { 584 for (int i = 0; i < arg_count; i++) {
573 Visit(args->at(i)); 585 Visit(args->at(i));
574 ASSERT_EQ(Expression::kValue, args->at(i)->context()); 586 ASSERT_EQ(Expression::kValue, args->at(i)->context());
575 } 587 }
576 // Record source position for debugger 588 // Record source position for debugger.
577 SetSourcePosition(expr->position()); 589 SetSourcePosition(expr->position());
578 // Call the IC initialization code. 590 // Call the IC initialization code.
579 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 591 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
580 NOT_IN_LOOP); 592 NOT_IN_LOOP);
581 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 593 __ call(ic, reloc_info);
582 // Restore context register. 594 // Restore context register.
583 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 595 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
584 // Discard the function left on TOS. 596 // Discard the function left on TOS.
585 DropAndMove(expr->context(), eax); 597 DropAndMove(expr->context(), eax);
586 } 598 }
587 599
588 600
601 void FastCodeGenerator::EmitCallWithStub(Call* expr) {
602 // Code common for calls using the call stub.
603 ZoneList<Expression*>* args = expr->arguments();
604 int arg_count = args->length();
605 for (int i = 0; i < arg_count; i++) {
606 Visit(args->at(i));
607 }
608 // Record source position for debugger.
609 SetSourcePosition(expr->position());
610 CallFunctionStub stub(arg_count, NOT_IN_LOOP);
611 __ CallStub(&stub);
612 // Restore context register.
613 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
614 // Discard the function left on TOS.
615 DropAndMove(expr->context(), eax);
616 }
617
618
619 void FastCodeGenerator::VisitCall(Call* expr) {
620 Expression* fun = expr->expression();
621
622 if (fun->AsProperty() != NULL) {
623 // Call on a property.
624 Property* prop = fun->AsProperty();
625 Literal* key = prop->key()->AsLiteral();
626 if (key != NULL && key->handle()->IsSymbol()) {
627 // Call on a named property: foo.x(1,2,3)
628 __ push(Immediate(key->handle()));
629 Visit(prop->obj());
630 // Use call IC.
631 EmitCallWithIC(expr, RelocInfo::CODE_TARGET);
632 } else {
633 // Call on a keyed property: foo[key](1,2,3)
634 // Use a keyed load IC followed by a call IC.
635 Visit(prop->obj());
636 Visit(prop->key());
637 // Record source position of property.
638 SetSourcePosition(prop->position());
639 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
640 __ call(ic, RelocInfo::CODE_TARGET);
641 // By emitting a nop we make sure that we do not have a "test eax,..."
642 // instruction after the call it is treated specially by the LoadIC code.
643 __ nop();
644 // Drop key left on the stack by IC.
645 __ add(Operand(esp), Immediate(kPointerSize));
646 // Pop receiver.
647 __ pop(ebx);
648 // Push result (function).
649 __ push(eax);
650 // Push receiver object on stack.
651 if (prop->is_synthetic()) {
652 __ push(CodeGenerator::GlobalObject());
653 } else {
654 __ push(ebx);
655 }
656 EmitCallWithStub(expr);
657 }
658 } else if (fun->AsVariableProxy()->AsVariable() != NULL) {
659 // Call on a global variable
660 Variable* var = fun->AsVariableProxy()->AsVariable();
661 ASSERT(var != NULL && !var->is_this() && var->is_global());
662 ASSERT(!var->is_possibly_eval());
663 __ push(Immediate(var->name()));
664 // Push global object (receiver).
665 __ push(CodeGenerator::GlobalObject());
666 EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
667 } else {
668 // Calls we cannot handle right now.
669 // Should bailout in the CodeGenSelector.
670 UNREACHABLE();
671 }
672 }
673
589 void FastCodeGenerator::VisitCallNew(CallNew* expr) { 674 void FastCodeGenerator::VisitCallNew(CallNew* expr) {
590 Comment cmnt(masm_, "[ CallNew"); 675 Comment cmnt(masm_, "[ CallNew");
591 // According to ECMA-262, section 11.2.2, page 44, the function 676 // According to ECMA-262, section 11.2.2, page 44, the function
592 // expression in new calls must be evaluated before the 677 // expression in new calls must be evaluated before the
593 // arguments. 678 // arguments.
594 // Push function on the stack. 679 // Push function on the stack.
595 Visit(expr->expression()); 680 Visit(expr->expression());
596 ASSERT_EQ(Expression::kValue, expr->expression()->context()); 681 ASSERT_EQ(Expression::kValue, expr->expression()->context());
597 682
598 // Push global object (receiver). 683 // Push global object (receiver).
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 } 853 }
769 // Save or discard the right-hand value as needed. 854 // Save or discard the right-hand value as needed.
770 Visit(right); 855 Visit(right);
771 ASSERT_EQ(context, right->context()); 856 ASSERT_EQ(context, right->context());
772 857
773 __ bind(&done); 858 __ bind(&done);
774 } 859 }
775 860
776 861
777 } } // namespace v8::internal 862 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.cc ('k') | src/x64/codegen-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698