OLD | NEW |
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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 } | 92 } |
93 | 93 |
94 { Comment cmnt(masm_, "[ Body"); | 94 { Comment cmnt(masm_, "[ Body"); |
95 VisitStatements(fun->body()); | 95 VisitStatements(fun->body()); |
96 } | 96 } |
97 | 97 |
98 { Comment cmnt(masm_, "[ return <undefined>;"); | 98 { Comment cmnt(masm_, "[ return <undefined>;"); |
99 // Emit a 'return undefined' in case control fell off the end of the | 99 // Emit a 'return undefined' in case control fell off the end of the |
100 // body. | 100 // body. |
101 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 101 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
102 SetReturnPosition(fun); | 102 } |
103 if (FLAG_trace) { | 103 { Comment cmnt(masm_, "Return sequence"); |
104 // Push the return value on the stack as the parameter. | 104 if (return_label_.is_bound()) { |
105 // Runtime::TraceExit returns its parameter in r0. | 105 __ b(&return_label_); |
106 __ push(r0); | 106 } else { |
107 __ CallRuntime(Runtime::kTraceExit, 1); | 107 __ bind(&return_label_); |
| 108 SetReturnPosition(fun); |
| 109 if (FLAG_trace) { |
| 110 // Push the return value on the stack as the parameter. |
| 111 // Runtime::TraceExit returns its parameter in r0. |
| 112 __ push(r0); |
| 113 __ CallRuntime(Runtime::kTraceExit, 1); |
| 114 } |
| 115 __ RecordJSReturn(); |
| 116 __ mov(sp, fp); |
| 117 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 118 int num_parameters = function_->scope()->num_parameters(); |
| 119 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); |
| 120 __ Jump(lr); |
108 } | 121 } |
109 | |
110 __ RecordJSReturn(); | |
111 __ mov(sp, fp); | |
112 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | |
113 int num_parameters = function_->scope()->num_parameters(); | |
114 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); | |
115 __ Jump(lr); | |
116 } | 122 } |
117 } | 123 } |
118 | 124 |
119 | 125 |
120 void FastCodeGenerator::Move(Expression::Context context, Slot* source) { | 126 void FastCodeGenerator::Move(Expression::Context context, Slot* source) { |
121 switch (context) { | 127 switch (context) { |
122 case Expression::kUninitialized: | 128 case Expression::kUninitialized: |
123 UNREACHABLE(); | 129 UNREACHABLE(); |
124 case Expression::kEffect: | 130 case Expression::kEffect: |
125 break; | 131 break; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 SetStatementPosition(stmt); | 182 SetStatementPosition(stmt); |
177 Expression* expr = stmt->expression(); | 183 Expression* expr = stmt->expression(); |
178 // Complete the statement based on the type of the subexpression. | 184 // Complete the statement based on the type of the subexpression. |
179 if (expr->AsLiteral() != NULL) { | 185 if (expr->AsLiteral() != NULL) { |
180 __ mov(r0, Operand(expr->AsLiteral()->handle())); | 186 __ mov(r0, Operand(expr->AsLiteral()->handle())); |
181 } else { | 187 } else { |
182 ASSERT_EQ(Expression::kValue, expr->context()); | 188 ASSERT_EQ(Expression::kValue, expr->context()); |
183 Visit(expr); | 189 Visit(expr); |
184 __ pop(r0); | 190 __ pop(r0); |
185 } | 191 } |
186 | 192 if (return_label_.is_bound()) { |
187 if (FLAG_trace) { | 193 __ b(&return_label_); |
188 __ push(r0); | 194 } else { |
189 __ CallRuntime(Runtime::kTraceExit, 1); | 195 __ bind(&return_label_); |
| 196 if (FLAG_trace) { |
| 197 __ push(r0); |
| 198 __ CallRuntime(Runtime::kTraceExit, 1); |
| 199 } |
| 200 __ RecordJSReturn(); |
| 201 __ mov(sp, fp); |
| 202 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 203 int num_parameters = function_->scope()->num_parameters(); |
| 204 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); |
| 205 __ Jump(lr); |
190 } | 206 } |
191 | |
192 __ RecordJSReturn(); | |
193 __ mov(sp, fp); | |
194 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | |
195 int num_parameters = function_->scope()->num_parameters(); | |
196 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); | |
197 __ Jump(lr); | |
198 } | 207 } |
199 | 208 |
200 | 209 |
201 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 210 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
202 Comment cmnt(masm_, "[ FunctionLiteral"); | 211 Comment cmnt(masm_, "[ FunctionLiteral"); |
203 | 212 |
204 // Build the function boilerplate and instantiate it. | 213 // Build the function boilerplate and instantiate it. |
205 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); | 214 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); |
206 if (HasStackOverflow()) return; | 215 if (HasStackOverflow()) return; |
207 | 216 |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 // Do a KEYED property load. | 567 // Do a KEYED property load. |
559 Visit(expr->key()); | 568 Visit(expr->key()); |
560 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 569 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
561 __ Call(ic, RelocInfo::CODE_TARGET); | 570 __ Call(ic, RelocInfo::CODE_TARGET); |
562 // Drop key and receiver left on the stack by IC. | 571 // Drop key and receiver left on the stack by IC. |
563 __ pop(); | 572 __ pop(); |
564 } | 573 } |
565 DropAndMove(expr->context(), r0); | 574 DropAndMove(expr->context(), r0); |
566 } | 575 } |
567 | 576 |
| 577 void FastCodeGenerator::EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info) { |
| 578 // Code common for calls using the IC. |
| 579 ZoneList<Expression*>* args = expr->arguments(); |
| 580 int arg_count = args->length(); |
| 581 for (int i = 0; i < arg_count; i++) { |
| 582 Visit(args->at(i)); |
| 583 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
| 584 } |
| 585 // Record source position for debugger. |
| 586 SetSourcePosition(expr->position()); |
| 587 // Call the IC initialization code. |
| 588 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 589 NOT_IN_LOOP); |
| 590 __ Call(ic, reloc_info); |
| 591 // Restore context register. |
| 592 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 593 // Discard the function left on TOS. |
| 594 DropAndMove(expr->context(), r0); |
| 595 } |
| 596 |
| 597 |
| 598 void FastCodeGenerator::EmitCallWithStub(Call* expr) { |
| 599 // Code common for calls using the call stub. |
| 600 ZoneList<Expression*>* args = expr->arguments(); |
| 601 int arg_count = args->length(); |
| 602 for (int i = 0; i < arg_count; i++) { |
| 603 Visit(args->at(i)); |
| 604 } |
| 605 // Record source position for debugger. |
| 606 SetSourcePosition(expr->position()); |
| 607 CallFunctionStub stub(arg_count, NOT_IN_LOOP); |
| 608 __ CallStub(&stub); |
| 609 // Restore context register. |
| 610 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 611 // Discard the function left on TOS. |
| 612 DropAndMove(expr->context(), r0); |
| 613 } |
| 614 |
568 | 615 |
569 void FastCodeGenerator::VisitCall(Call* expr) { | 616 void FastCodeGenerator::VisitCall(Call* expr) { |
570 Comment cmnt(masm_, "[ Call"); | |
571 Expression* fun = expr->expression(); | 617 Expression* fun = expr->expression(); |
572 ZoneList<Expression*>* args = expr->arguments(); | |
573 Variable* var = fun->AsVariableProxy()->AsVariable(); | |
574 ASSERT(var != NULL && !var->is_this() && var->is_global()); | |
575 ASSERT(!var->is_possibly_eval()); | |
576 | 618 |
577 __ mov(r1, Operand(var->name())); | 619 if (fun->AsProperty() != NULL) { |
578 // Push global object as receiver. | 620 // Call on a property. |
579 __ ldr(r0, CodeGenerator::GlobalObject()); | 621 Property* prop = fun->AsProperty(); |
580 __ stm(db_w, sp, r1.bit() | r0.bit()); | 622 Literal* key = prop->key()->AsLiteral(); |
581 int arg_count = args->length(); | 623 if (key != NULL && key->handle()->IsSymbol()) { |
582 for (int i = 0; i < arg_count; i++) { | 624 // Call on a named property: foo.x(1,2,3) |
583 Visit(args->at(i)); | 625 __ mov(r0, Operand(key->handle())); |
584 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 626 __ push(r0); |
| 627 Visit(prop->obj()); |
| 628 // Use call IC. |
| 629 EmitCallWithIC(expr, RelocInfo::CODE_TARGET); |
| 630 } else { |
| 631 // Call on a keyed property : foo[key](1,2,3) |
| 632 // Use a keyed load IC followed by a call IC. |
| 633 Visit(prop->obj()); |
| 634 Visit(prop->key()); |
| 635 // Record source position of property. |
| 636 SetSourcePosition(prop->position()); |
| 637 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 638 __ Call(ic, RelocInfo::CODE_TARGET); |
| 639 // Load receiver object into r1. |
| 640 if (prop->is_synthetic()) { |
| 641 __ ldr(r1, CodeGenerator::GlobalObject()); |
| 642 } else { |
| 643 __ ldr(r1, MemOperand(sp, kPointerSize)); |
| 644 } |
| 645 // Overwrite (object, key) with (function, receiver). |
| 646 __ str(r0, MemOperand(sp, kPointerSize)); |
| 647 __ str(r1, MemOperand(sp)); |
| 648 EmitCallWithStub(expr); |
| 649 } |
| 650 } else if (fun->AsVariableProxy()->AsVariable() != NULL) { |
| 651 // Call on a global variable |
| 652 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 653 ASSERT(var != NULL && !var->is_this() && var->is_global()); |
| 654 ASSERT(!var->is_possibly_eval()); |
| 655 __ mov(r1, Operand(var->name())); |
| 656 // Push global object as receiver. |
| 657 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 658 __ stm(db_w, sp, r1.bit() | r0.bit()); |
| 659 EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT); |
| 660 } else { |
| 661 // Calls we cannot handle right now. |
| 662 // Should bailout in the CodeGenSelector. |
| 663 UNREACHABLE(); |
585 } | 664 } |
586 // Record source position for debugger | |
587 SetSourcePosition(expr->position()); | |
588 // Call the IC initialization code. | |
589 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | |
590 NOT_IN_LOOP); | |
591 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
592 // Restore context register. | |
593 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
594 DropAndMove(expr->context(), r0); | |
595 } | 665 } |
596 | 666 |
597 | 667 |
598 void FastCodeGenerator::VisitCallNew(CallNew* expr) { | 668 void FastCodeGenerator::VisitCallNew(CallNew* expr) { |
599 Comment cmnt(masm_, "[ CallNew"); | 669 Comment cmnt(masm_, "[ CallNew"); |
600 // According to ECMA-262, section 11.2.2, page 44, the function | 670 // According to ECMA-262, section 11.2.2, page 44, the function |
601 // expression in new calls must be evaluated before the | 671 // expression in new calls must be evaluated before the |
602 // arguments. | 672 // arguments. |
603 // Push function on the stack. | 673 // Push function on the stack. |
604 Visit(expr->expression()); | 674 Visit(expr->expression()); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 // Discard the left-hand value if present on the stack. | 810 // Discard the left-hand value if present on the stack. |
741 if (context == Expression::kValue) __ pop(); | 811 if (context == Expression::kValue) __ pop(); |
742 // Save or discard the right-hand value as needed. | 812 // Save or discard the right-hand value as needed. |
743 Visit(right); | 813 Visit(right); |
744 ASSERT_EQ(context, right->context()); | 814 ASSERT_EQ(context, right->context()); |
745 | 815 |
746 __ bind(&done); | 816 __ bind(&done); |
747 } | 817 } |
748 | 818 |
749 } } // namespace v8::internal | 819 } } // namespace v8::internal |
OLD | NEW |