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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 // formal parameter count expected by the function. | 44 // formal parameter count expected by the function. |
45 // | 45 // |
46 // The live registers are: | 46 // The live registers are: |
47 // o rdi: the JS function object being called (ie, ourselves) | 47 // o rdi: the JS function object being called (ie, ourselves) |
48 // o rsi: our context | 48 // o rsi: our context |
49 // o rbp: our caller's frame pointer | 49 // o rbp: our caller's frame pointer |
50 // o rsp: stack pointer (pointing to return address) | 50 // o rsp: stack pointer (pointing to return address) |
51 // | 51 // |
52 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 52 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
53 // frames-x64.h for its layout. | 53 // frames-x64.h for its layout. |
54 void FastCodeGenerator::Generate(FunctionLiteral* fun) { | 54 void FullCodeGenerator::Generate(FunctionLiteral* fun) { |
55 function_ = fun; | 55 function_ = fun; |
56 SetFunctionPosition(fun); | 56 SetFunctionPosition(fun); |
57 | 57 |
58 __ push(rbp); // Caller's frame pointer. | 58 __ push(rbp); // Caller's frame pointer. |
59 __ movq(rbp, rsp); | 59 __ movq(rbp, rsp); |
60 __ push(rsi); // Callee's context. | 60 __ push(rsi); // Callee's context. |
61 __ push(rdi); // Callee's JS Function. | 61 __ push(rdi); // Callee's JS Function. |
62 | 62 |
63 { Comment cmnt(masm_, "[ Allocate locals"); | 63 { Comment cmnt(masm_, "[ Allocate locals"); |
64 int locals_count = fun->scope()->num_stack_slots(); | 64 int locals_count = fun->scope()->num_stack_slots(); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 } | 154 } |
155 | 155 |
156 { Comment cmnt(masm_, "[ return <undefined>;"); | 156 { Comment cmnt(masm_, "[ return <undefined>;"); |
157 // Emit a 'return undefined' in case control fell off the end of the body. | 157 // Emit a 'return undefined' in case control fell off the end of the body. |
158 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 158 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
159 EmitReturnSequence(function_->end_position()); | 159 EmitReturnSequence(function_->end_position()); |
160 } | 160 } |
161 } | 161 } |
162 | 162 |
163 | 163 |
164 void FastCodeGenerator::EmitReturnSequence(int position) { | 164 void FullCodeGenerator::EmitReturnSequence(int position) { |
165 Comment cmnt(masm_, "[ Return sequence"); | 165 Comment cmnt(masm_, "[ Return sequence"); |
166 if (return_label_.is_bound()) { | 166 if (return_label_.is_bound()) { |
167 __ jmp(&return_label_); | 167 __ jmp(&return_label_); |
168 } else { | 168 } else { |
169 __ bind(&return_label_); | 169 __ bind(&return_label_); |
170 if (FLAG_trace) { | 170 if (FLAG_trace) { |
171 __ push(rax); | 171 __ push(rax); |
172 __ CallRuntime(Runtime::kTraceExit, 1); | 172 __ CallRuntime(Runtime::kTraceExit, 1); |
173 } | 173 } |
174 #ifdef DEBUG | 174 #ifdef DEBUG |
(...skipping 18 matching lines...) Expand all Loading... |
193 } | 193 } |
194 // Check that the size of the code used for returning matches what is | 194 // Check that the size of the code used for returning matches what is |
195 // expected by the debugger. | 195 // expected by the debugger. |
196 ASSERT_EQ(Assembler::kJSReturnSequenceLength, | 196 ASSERT_EQ(Assembler::kJSReturnSequenceLength, |
197 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 197 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
198 #endif | 198 #endif |
199 } | 199 } |
200 } | 200 } |
201 | 201 |
202 | 202 |
203 void FastCodeGenerator::Apply(Expression::Context context, Register reg) { | 203 void FullCodeGenerator::Apply(Expression::Context context, Register reg) { |
204 switch (context) { | 204 switch (context) { |
205 case Expression::kUninitialized: | 205 case Expression::kUninitialized: |
206 UNREACHABLE(); | 206 UNREACHABLE(); |
207 | 207 |
208 case Expression::kEffect: | 208 case Expression::kEffect: |
209 // Nothing to do. | 209 // Nothing to do. |
210 break; | 210 break; |
211 | 211 |
212 case Expression::kValue: | 212 case Expression::kValue: |
213 // Move value into place. | 213 // Move value into place. |
(...skipping 22 matching lines...) Expand all Loading... |
236 case kStack: | 236 case kStack: |
237 __ push(result_register()); | 237 __ push(result_register()); |
238 break; | 238 break; |
239 } | 239 } |
240 DoTest(context); | 240 DoTest(context); |
241 break; | 241 break; |
242 } | 242 } |
243 } | 243 } |
244 | 244 |
245 | 245 |
246 void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 246 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
247 switch (context) { | 247 switch (context) { |
248 case Expression::kUninitialized: | 248 case Expression::kUninitialized: |
249 UNREACHABLE(); | 249 UNREACHABLE(); |
250 case Expression::kEffect: | 250 case Expression::kEffect: |
251 // Nothing to do. | 251 // Nothing to do. |
252 break; | 252 break; |
253 case Expression::kValue: { | 253 case Expression::kValue: { |
254 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); | 254 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); |
255 switch (location_) { | 255 switch (location_) { |
256 case kAccumulator: | 256 case kAccumulator: |
(...skipping 21 matching lines...) Expand all Loading... |
278 case kStack: | 278 case kStack: |
279 __ push(result_register()); | 279 __ push(result_register()); |
280 break; | 280 break; |
281 } | 281 } |
282 DoTest(context); | 282 DoTest(context); |
283 break; | 283 break; |
284 } | 284 } |
285 } | 285 } |
286 | 286 |
287 | 287 |
288 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 288 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
289 switch (context) { | 289 switch (context) { |
290 case Expression::kUninitialized: | 290 case Expression::kUninitialized: |
291 UNREACHABLE(); | 291 UNREACHABLE(); |
292 case Expression::kEffect: | 292 case Expression::kEffect: |
293 // Nothing to do. | 293 // Nothing to do. |
294 break; | 294 break; |
295 case Expression::kValue: | 295 case Expression::kValue: |
296 switch (location_) { | 296 switch (location_) { |
297 case kAccumulator: | 297 case kAccumulator: |
298 __ Move(result_register(), lit->handle()); | 298 __ Move(result_register(), lit->handle()); |
(...skipping 18 matching lines...) Expand all Loading... |
317 case kStack: | 317 case kStack: |
318 __ push(result_register()); | 318 __ push(result_register()); |
319 break; | 319 break; |
320 } | 320 } |
321 DoTest(context); | 321 DoTest(context); |
322 break; | 322 break; |
323 } | 323 } |
324 } | 324 } |
325 | 325 |
326 | 326 |
327 void FastCodeGenerator::ApplyTOS(Expression::Context context) { | 327 void FullCodeGenerator::ApplyTOS(Expression::Context context) { |
328 switch (context) { | 328 switch (context) { |
329 case Expression::kUninitialized: | 329 case Expression::kUninitialized: |
330 UNREACHABLE(); | 330 UNREACHABLE(); |
331 | 331 |
332 case Expression::kEffect: | 332 case Expression::kEffect: |
333 __ Drop(1); | 333 __ Drop(1); |
334 break; | 334 break; |
335 | 335 |
336 case Expression::kValue: | 336 case Expression::kValue: |
337 switch (location_) { | 337 switch (location_) { |
(...skipping 19 matching lines...) Expand all Loading... |
357 case kStack: | 357 case kStack: |
358 __ movq(result_register(), Operand(rsp, 0)); | 358 __ movq(result_register(), Operand(rsp, 0)); |
359 break; | 359 break; |
360 } | 360 } |
361 DoTest(context); | 361 DoTest(context); |
362 break; | 362 break; |
363 } | 363 } |
364 } | 364 } |
365 | 365 |
366 | 366 |
367 void FastCodeGenerator::DropAndApply(int count, | 367 void FullCodeGenerator::DropAndApply(int count, |
368 Expression::Context context, | 368 Expression::Context context, |
369 Register reg) { | 369 Register reg) { |
370 ASSERT(count > 0); | 370 ASSERT(count > 0); |
371 ASSERT(!reg.is(rsp)); | 371 ASSERT(!reg.is(rsp)); |
372 switch (context) { | 372 switch (context) { |
373 case Expression::kUninitialized: | 373 case Expression::kUninitialized: |
374 UNREACHABLE(); | 374 UNREACHABLE(); |
375 | 375 |
376 case Expression::kEffect: | 376 case Expression::kEffect: |
377 __ Drop(count); | 377 __ Drop(count); |
(...skipping 30 matching lines...) Expand all Loading... |
408 __ movq(result_register(), reg); | 408 __ movq(result_register(), reg); |
409 __ movq(Operand(rsp, 0), result_register()); | 409 __ movq(Operand(rsp, 0), result_register()); |
410 break; | 410 break; |
411 } | 411 } |
412 DoTest(context); | 412 DoTest(context); |
413 break; | 413 break; |
414 } | 414 } |
415 } | 415 } |
416 | 416 |
417 | 417 |
418 void FastCodeGenerator::Apply(Expression::Context context, | 418 void FullCodeGenerator::Apply(Expression::Context context, |
419 Label* materialize_true, | 419 Label* materialize_true, |
420 Label* materialize_false) { | 420 Label* materialize_false) { |
421 switch (context) { | 421 switch (context) { |
422 case Expression::kUninitialized: | 422 case Expression::kUninitialized: |
423 | 423 |
424 case Expression::kEffect: | 424 case Expression::kEffect: |
425 ASSERT_EQ(materialize_true, materialize_false); | 425 ASSERT_EQ(materialize_true, materialize_false); |
426 __ bind(materialize_true); | 426 __ bind(materialize_true); |
427 break; | 427 break; |
428 | 428 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 case kStack: | 473 case kStack: |
474 __ Push(Factory::false_value()); | 474 __ Push(Factory::false_value()); |
475 break; | 475 break; |
476 } | 476 } |
477 __ jmp(false_label_); | 477 __ jmp(false_label_); |
478 break; | 478 break; |
479 } | 479 } |
480 } | 480 } |
481 | 481 |
482 | 482 |
483 void FastCodeGenerator::DoTest(Expression::Context context) { | 483 void FullCodeGenerator::DoTest(Expression::Context context) { |
484 // The value to test is in the accumulator. If the value might be needed | 484 // The value to test is in the accumulator. If the value might be needed |
485 // on the stack (value/test and test/value contexts with a stack location | 485 // on the stack (value/test and test/value contexts with a stack location |
486 // desired), then the value is already duplicated on the stack. | 486 // desired), then the value is already duplicated on the stack. |
487 ASSERT_NE(NULL, true_label_); | 487 ASSERT_NE(NULL, true_label_); |
488 ASSERT_NE(NULL, false_label_); | 488 ASSERT_NE(NULL, false_label_); |
489 | 489 |
490 // In value/test and test/value expression contexts with stack as the | 490 // In value/test and test/value expression contexts with stack as the |
491 // desired location, there is already an extra value on the stack. Use a | 491 // desired location, there is already an extra value on the stack. Use a |
492 // label to discard it if unneeded. | 492 // label to discard it if unneeded. |
493 Label discard; | 493 Label discard; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
607 break; | 607 break; |
608 } | 608 } |
609 __ bind(&discard); | 609 __ bind(&discard); |
610 __ Drop(1); | 610 __ Drop(1); |
611 __ jmp(true_label_); | 611 __ jmp(true_label_); |
612 break; | 612 break; |
613 } | 613 } |
614 } | 614 } |
615 | 615 |
616 | 616 |
617 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 617 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
618 switch (slot->type()) { | 618 switch (slot->type()) { |
619 case Slot::PARAMETER: | 619 case Slot::PARAMETER: |
620 case Slot::LOCAL: | 620 case Slot::LOCAL: |
621 return Operand(rbp, SlotOffset(slot)); | 621 return Operand(rbp, SlotOffset(slot)); |
622 case Slot::CONTEXT: { | 622 case Slot::CONTEXT: { |
623 int context_chain_length = | 623 int context_chain_length = |
624 function_->scope()->ContextChainLength(slot->var()->scope()); | 624 function_->scope()->ContextChainLength(slot->var()->scope()); |
625 __ LoadContext(scratch, context_chain_length); | 625 __ LoadContext(scratch, context_chain_length); |
626 return CodeGenerator::ContextOperand(scratch, slot->index()); | 626 return CodeGenerator::ContextOperand(scratch, slot->index()); |
627 } | 627 } |
628 case Slot::LOOKUP: | 628 case Slot::LOOKUP: |
629 UNREACHABLE(); | 629 UNREACHABLE(); |
630 } | 630 } |
631 UNREACHABLE(); | 631 UNREACHABLE(); |
632 return Operand(rax, 0); | 632 return Operand(rax, 0); |
633 } | 633 } |
634 | 634 |
635 | 635 |
636 void FastCodeGenerator::Move(Register destination, Slot* source) { | 636 void FullCodeGenerator::Move(Register destination, Slot* source) { |
637 MemOperand location = EmitSlotSearch(source, destination); | 637 MemOperand location = EmitSlotSearch(source, destination); |
638 __ movq(destination, location); | 638 __ movq(destination, location); |
639 } | 639 } |
640 | 640 |
641 | 641 |
642 void FastCodeGenerator::Move(Slot* dst, | 642 void FullCodeGenerator::Move(Slot* dst, |
643 Register src, | 643 Register src, |
644 Register scratch1, | 644 Register scratch1, |
645 Register scratch2) { | 645 Register scratch2) { |
646 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 646 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
647 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 647 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
648 MemOperand location = EmitSlotSearch(dst, scratch1); | 648 MemOperand location = EmitSlotSearch(dst, scratch1); |
649 __ movq(location, src); | 649 __ movq(location, src); |
650 // Emit the write barrier code if the location is in the heap. | 650 // Emit the write barrier code if the location is in the heap. |
651 if (dst->type() == Slot::CONTEXT) { | 651 if (dst->type() == Slot::CONTEXT) { |
652 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | 652 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
653 __ RecordWrite(scratch1, offset, src, scratch2); | 653 __ RecordWrite(scratch1, offset, src, scratch2); |
654 } | 654 } |
655 } | 655 } |
656 | 656 |
657 | 657 |
658 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { | 658 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
659 Comment cmnt(masm_, "[ Declaration"); | 659 Comment cmnt(masm_, "[ Declaration"); |
660 Variable* var = decl->proxy()->var(); | 660 Variable* var = decl->proxy()->var(); |
661 ASSERT(var != NULL); // Must have been resolved. | 661 ASSERT(var != NULL); // Must have been resolved. |
662 Slot* slot = var->slot(); | 662 Slot* slot = var->slot(); |
663 Property* prop = var->AsProperty(); | 663 Property* prop = var->AsProperty(); |
664 | 664 |
665 if (slot != NULL) { | 665 if (slot != NULL) { |
666 switch (slot->type()) { | 666 switch (slot->type()) { |
667 case Slot::PARAMETER: | 667 case Slot::PARAMETER: |
668 case Slot::LOCAL: | 668 case Slot::LOCAL: |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 __ nop(); | 747 __ nop(); |
748 | 748 |
749 // Value in rax is ignored (declarations are statements). Receiver | 749 // Value in rax is ignored (declarations are statements). Receiver |
750 // and key on stack are discarded. | 750 // and key on stack are discarded. |
751 __ Drop(2); | 751 __ Drop(2); |
752 } | 752 } |
753 } | 753 } |
754 } | 754 } |
755 | 755 |
756 | 756 |
757 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 757 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
758 // Call the runtime to declare the globals. | 758 // Call the runtime to declare the globals. |
759 __ push(rsi); // The context is the first argument. | 759 __ push(rsi); // The context is the first argument. |
760 __ Push(pairs); | 760 __ Push(pairs); |
761 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); | 761 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); |
762 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 762 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
763 // Return value is ignored. | 763 // Return value is ignored. |
764 } | 764 } |
765 | 765 |
766 | 766 |
767 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 767 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
768 Comment cmnt(masm_, "[ FunctionLiteral"); | 768 Comment cmnt(masm_, "[ FunctionLiteral"); |
769 | 769 |
770 // Build the function boilerplate and instantiate it. | 770 // Build the function boilerplate and instantiate it. |
771 Handle<JSFunction> boilerplate = | 771 Handle<JSFunction> boilerplate = |
772 Compiler::BuildBoilerplate(expr, script_, this); | 772 Compiler::BuildBoilerplate(expr, script_, this); |
773 if (HasStackOverflow()) return; | 773 if (HasStackOverflow()) return; |
774 | 774 |
775 ASSERT(boilerplate->IsBoilerplate()); | 775 ASSERT(boilerplate->IsBoilerplate()); |
776 | 776 |
777 // Create a new closure. | 777 // Create a new closure. |
778 __ push(rsi); | 778 __ push(rsi); |
779 __ Push(boilerplate); | 779 __ Push(boilerplate); |
780 __ CallRuntime(Runtime::kNewClosure, 2); | 780 __ CallRuntime(Runtime::kNewClosure, 2); |
781 Apply(context_, rax); | 781 Apply(context_, rax); |
782 } | 782 } |
783 | 783 |
784 | 784 |
785 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 785 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
786 Comment cmnt(masm_, "[ VariableProxy"); | 786 Comment cmnt(masm_, "[ VariableProxy"); |
787 EmitVariableLoad(expr->var(), context_); | 787 EmitVariableLoad(expr->var(), context_); |
788 } | 788 } |
789 | 789 |
790 | 790 |
791 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 791 void FullCodeGenerator::EmitVariableLoad(Variable* var, |
792 Expression::Context context) { | 792 Expression::Context context) { |
793 Expression* rewrite = var->rewrite(); | 793 Expression* rewrite = var->rewrite(); |
794 if (rewrite == NULL) { | 794 if (rewrite == NULL) { |
795 ASSERT(var->is_global()); | 795 ASSERT(var->is_global()); |
796 Comment cmnt(masm_, "Global variable"); | 796 Comment cmnt(masm_, "Global variable"); |
797 // Use inline caching. Variable name is passed in rcx and the global | 797 // Use inline caching. Variable name is passed in rcx and the global |
798 // object on the stack. | 798 // object on the stack. |
799 __ push(CodeGenerator::GlobalObject()); | 799 __ push(CodeGenerator::GlobalObject()); |
800 __ Move(rcx, var->name()); | 800 __ Move(rcx, var->name()); |
801 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 801 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 __ call(ic, RelocInfo::CODE_TARGET); | 857 __ call(ic, RelocInfo::CODE_TARGET); |
858 // Notice: We must not have a "test rax, ..." instruction after the | 858 // Notice: We must not have a "test rax, ..." instruction after the |
859 // call. It is treated specially by the LoadIC code. | 859 // call. It is treated specially by the LoadIC code. |
860 __ nop(); | 860 __ nop(); |
861 // Drop key and object left on the stack by IC, and push the result. | 861 // Drop key and object left on the stack by IC, and push the result. |
862 DropAndApply(2, context, rax); | 862 DropAndApply(2, context, rax); |
863 } | 863 } |
864 } | 864 } |
865 | 865 |
866 | 866 |
867 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 867 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
868 Comment cmnt(masm_, "[ RegExpLiteral"); | 868 Comment cmnt(masm_, "[ RegExpLiteral"); |
869 Label done; | 869 Label done; |
870 // Registers will be used as follows: | 870 // Registers will be used as follows: |
871 // rdi = JS function. | 871 // rdi = JS function. |
872 // rbx = literals array. | 872 // rbx = literals array. |
873 // rax = regexp literal. | 873 // rax = regexp literal. |
874 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 874 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
875 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 875 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
876 int literal_offset = | 876 int literal_offset = |
877 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 877 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
878 __ movq(rax, FieldOperand(rbx, literal_offset)); | 878 __ movq(rax, FieldOperand(rbx, literal_offset)); |
879 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 879 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
880 __ j(not_equal, &done); | 880 __ j(not_equal, &done); |
881 // Create regexp literal using runtime function | 881 // Create regexp literal using runtime function |
882 // Result will be in rax. | 882 // Result will be in rax. |
883 __ push(rbx); | 883 __ push(rbx); |
884 __ Push(Smi::FromInt(expr->literal_index())); | 884 __ Push(Smi::FromInt(expr->literal_index())); |
885 __ Push(expr->pattern()); | 885 __ Push(expr->pattern()); |
886 __ Push(expr->flags()); | 886 __ Push(expr->flags()); |
887 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 887 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
888 __ bind(&done); | 888 __ bind(&done); |
889 Apply(context_, rax); | 889 Apply(context_, rax); |
890 } | 890 } |
891 | 891 |
892 | 892 |
893 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 893 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
894 Comment cmnt(masm_, "[ ObjectLiteral"); | 894 Comment cmnt(masm_, "[ ObjectLiteral"); |
895 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 895 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
896 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 896 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
897 __ Push(Smi::FromInt(expr->literal_index())); | 897 __ Push(Smi::FromInt(expr->literal_index())); |
898 __ Push(expr->constant_properties()); | 898 __ Push(expr->constant_properties()); |
899 if (expr->depth() > 1) { | 899 if (expr->depth() > 1) { |
900 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); | 900 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); |
901 } else { | 901 } else { |
902 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); | 902 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); |
903 } | 903 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 } | 953 } |
954 | 954 |
955 if (result_saved) { | 955 if (result_saved) { |
956 ApplyTOS(context_); | 956 ApplyTOS(context_); |
957 } else { | 957 } else { |
958 Apply(context_, rax); | 958 Apply(context_, rax); |
959 } | 959 } |
960 } | 960 } |
961 | 961 |
962 | 962 |
963 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 963 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
964 Comment cmnt(masm_, "[ ArrayLiteral"); | 964 Comment cmnt(masm_, "[ ArrayLiteral"); |
965 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 965 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
966 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); | 966 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); |
967 __ Push(Smi::FromInt(expr->literal_index())); | 967 __ Push(Smi::FromInt(expr->literal_index())); |
968 __ Push(expr->constant_elements()); | 968 __ Push(expr->constant_elements()); |
969 if (expr->depth() > 1) { | 969 if (expr->depth() > 1) { |
970 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 970 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); |
971 } else { | 971 } else { |
972 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 972 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); |
973 } | 973 } |
(...skipping 29 matching lines...) Expand all Loading... |
1003 } | 1003 } |
1004 | 1004 |
1005 if (result_saved) { | 1005 if (result_saved) { |
1006 ApplyTOS(context_); | 1006 ApplyTOS(context_); |
1007 } else { | 1007 } else { |
1008 Apply(context_, rax); | 1008 Apply(context_, rax); |
1009 } | 1009 } |
1010 } | 1010 } |
1011 | 1011 |
1012 | 1012 |
1013 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1013 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1014 SetSourcePosition(prop->position()); | 1014 SetSourcePosition(prop->position()); |
1015 Literal* key = prop->key()->AsLiteral(); | 1015 Literal* key = prop->key()->AsLiteral(); |
1016 __ Move(rcx, key->handle()); | 1016 __ Move(rcx, key->handle()); |
1017 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1017 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1018 __ Call(ic, RelocInfo::CODE_TARGET); | 1018 __ Call(ic, RelocInfo::CODE_TARGET); |
1019 __ nop(); | 1019 __ nop(); |
1020 } | 1020 } |
1021 | 1021 |
1022 | 1022 |
1023 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1023 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1024 SetSourcePosition(prop->position()); | 1024 SetSourcePosition(prop->position()); |
1025 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1025 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1026 __ Call(ic, RelocInfo::CODE_TARGET); | 1026 __ Call(ic, RelocInfo::CODE_TARGET); |
1027 __ nop(); | 1027 __ nop(); |
1028 } | 1028 } |
1029 | 1029 |
1030 | 1030 |
1031 void FastCodeGenerator::EmitBinaryOp(Token::Value op, | 1031 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
1032 Expression::Context context) { | 1032 Expression::Context context) { |
1033 __ push(result_register()); | 1033 __ push(result_register()); |
1034 GenericBinaryOpStub stub(op, | 1034 GenericBinaryOpStub stub(op, |
1035 NO_OVERWRITE, | 1035 NO_OVERWRITE, |
1036 NO_GENERIC_BINARY_FLAGS); | 1036 NO_GENERIC_BINARY_FLAGS); |
1037 __ CallStub(&stub); | 1037 __ CallStub(&stub); |
1038 Apply(context, rax); | 1038 Apply(context, rax); |
1039 } | 1039 } |
1040 | 1040 |
1041 | 1041 |
1042 void FastCodeGenerator::EmitVariableAssignment(Variable* var, | 1042 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1043 Expression::Context context) { | 1043 Expression::Context context) { |
1044 ASSERT(var != NULL); | 1044 ASSERT(var != NULL); |
1045 ASSERT(var->is_global() || var->slot() != NULL); | 1045 ASSERT(var->is_global() || var->slot() != NULL); |
1046 if (var->is_global()) { | 1046 if (var->is_global()) { |
1047 // Assignment to a global variable. Use inline caching for the | 1047 // Assignment to a global variable. Use inline caching for the |
1048 // assignment. Right-hand-side value is passed in rax, variable name in | 1048 // assignment. Right-hand-side value is passed in rax, variable name in |
1049 // rcx, and the global object on the stack. | 1049 // rcx, and the global object on the stack. |
1050 __ Move(rcx, var->name()); | 1050 __ Move(rcx, var->name()); |
1051 __ push(CodeGenerator::GlobalObject()); | 1051 __ push(CodeGenerator::GlobalObject()); |
1052 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1052 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
(...skipping 26 matching lines...) Expand all Loading... |
1079 } | 1079 } |
1080 Apply(context, result_register()); | 1080 Apply(context, result_register()); |
1081 } else { | 1081 } else { |
1082 // Variables rewritten as properties are not treated as variables in | 1082 // Variables rewritten as properties are not treated as variables in |
1083 // assignments. | 1083 // assignments. |
1084 UNREACHABLE(); | 1084 UNREACHABLE(); |
1085 } | 1085 } |
1086 } | 1086 } |
1087 | 1087 |
1088 | 1088 |
1089 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1089 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1090 // Assignment to a property, using a named store IC. | 1090 // Assignment to a property, using a named store IC. |
1091 Property* prop = expr->target()->AsProperty(); | 1091 Property* prop = expr->target()->AsProperty(); |
1092 ASSERT(prop != NULL); | 1092 ASSERT(prop != NULL); |
1093 ASSERT(prop->key()->AsLiteral() != NULL); | 1093 ASSERT(prop->key()->AsLiteral() != NULL); |
1094 | 1094 |
1095 // If the assignment starts a block of assignments to the same object, | 1095 // If the assignment starts a block of assignments to the same object, |
1096 // change to slow case to avoid the quadratic behavior of repeatedly | 1096 // change to slow case to avoid the quadratic behavior of repeatedly |
1097 // adding fast properties. | 1097 // adding fast properties. |
1098 if (expr->starts_initialization_block()) { | 1098 if (expr->starts_initialization_block()) { |
1099 __ push(result_register()); | 1099 __ push(result_register()); |
(...skipping 14 matching lines...) Expand all Loading... |
1114 __ push(rax); // Result of assignment, saved even if not needed. | 1114 __ push(rax); // Result of assignment, saved even if not needed. |
1115 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 1115 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
1116 __ CallRuntime(Runtime::kToFastProperties, 1); | 1116 __ CallRuntime(Runtime::kToFastProperties, 1); |
1117 __ pop(rax); | 1117 __ pop(rax); |
1118 } | 1118 } |
1119 | 1119 |
1120 DropAndApply(1, context_, rax); | 1120 DropAndApply(1, context_, rax); |
1121 } | 1121 } |
1122 | 1122 |
1123 | 1123 |
1124 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1124 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
1125 // Assignment to a property, using a keyed store IC. | 1125 // Assignment to a property, using a keyed store IC. |
1126 | 1126 |
1127 // If the assignment starts a block of assignments to the same object, | 1127 // If the assignment starts a block of assignments to the same object, |
1128 // change to slow case to avoid the quadratic behavior of repeatedly | 1128 // change to slow case to avoid the quadratic behavior of repeatedly |
1129 // adding fast properties. | 1129 // adding fast properties. |
1130 if (expr->starts_initialization_block()) { | 1130 if (expr->starts_initialization_block()) { |
1131 __ push(result_register()); | 1131 __ push(result_register()); |
1132 // Receiver is now under the key and value. | 1132 // Receiver is now under the key and value. |
1133 __ push(Operand(rsp, 2 * kPointerSize)); | 1133 __ push(Operand(rsp, 2 * kPointerSize)); |
1134 __ CallRuntime(Runtime::kToSlowProperties, 1); | 1134 __ CallRuntime(Runtime::kToSlowProperties, 1); |
(...skipping 15 matching lines...) Expand all Loading... |
1150 __ push(Operand(rsp, 2 * kPointerSize)); | 1150 __ push(Operand(rsp, 2 * kPointerSize)); |
1151 __ CallRuntime(Runtime::kToFastProperties, 1); | 1151 __ CallRuntime(Runtime::kToFastProperties, 1); |
1152 __ pop(rax); | 1152 __ pop(rax); |
1153 } | 1153 } |
1154 | 1154 |
1155 // Receiver and key are still on stack. | 1155 // Receiver and key are still on stack. |
1156 DropAndApply(2, context_, rax); | 1156 DropAndApply(2, context_, rax); |
1157 } | 1157 } |
1158 | 1158 |
1159 | 1159 |
1160 void FastCodeGenerator::VisitProperty(Property* expr) { | 1160 void FullCodeGenerator::VisitProperty(Property* expr) { |
1161 Comment cmnt(masm_, "[ Property"); | 1161 Comment cmnt(masm_, "[ Property"); |
1162 Expression* key = expr->key(); | 1162 Expression* key = expr->key(); |
1163 | 1163 |
1164 // Evaluate receiver. | 1164 // Evaluate receiver. |
1165 VisitForValue(expr->obj(), kStack); | 1165 VisitForValue(expr->obj(), kStack); |
1166 | 1166 |
1167 if (key->IsPropertyName()) { | 1167 if (key->IsPropertyName()) { |
1168 EmitNamedPropertyLoad(expr); | 1168 EmitNamedPropertyLoad(expr); |
1169 // Drop receiver left on the stack by IC. | 1169 // Drop receiver left on the stack by IC. |
1170 DropAndApply(1, context_, rax); | 1170 DropAndApply(1, context_, rax); |
1171 } else { | 1171 } else { |
1172 VisitForValue(expr->key(), kStack); | 1172 VisitForValue(expr->key(), kStack); |
1173 EmitKeyedPropertyLoad(expr); | 1173 EmitKeyedPropertyLoad(expr); |
1174 // Drop key and receiver left on the stack by IC. | 1174 // Drop key and receiver left on the stack by IC. |
1175 DropAndApply(2, context_, rax); | 1175 DropAndApply(2, context_, rax); |
1176 } | 1176 } |
1177 } | 1177 } |
1178 | 1178 |
1179 | 1179 |
1180 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1180 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
1181 Handle<Object> ignored, | 1181 Handle<Object> ignored, |
1182 RelocInfo::Mode mode) { | 1182 RelocInfo::Mode mode) { |
1183 // Code common for calls using the IC. | 1183 // Code common for calls using the IC. |
1184 ZoneList<Expression*>* args = expr->arguments(); | 1184 ZoneList<Expression*>* args = expr->arguments(); |
1185 int arg_count = args->length(); | 1185 int arg_count = args->length(); |
1186 for (int i = 0; i < arg_count; i++) { | 1186 for (int i = 0; i < arg_count; i++) { |
1187 VisitForValue(args->at(i), kStack); | 1187 VisitForValue(args->at(i), kStack); |
1188 } | 1188 } |
1189 // Record source position for debugger. | 1189 // Record source position for debugger. |
1190 SetSourcePosition(expr->position()); | 1190 SetSourcePosition(expr->position()); |
1191 // Call the IC initialization code. | 1191 // Call the IC initialization code. |
1192 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1192 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1193 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1193 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
1194 in_loop); | 1194 in_loop); |
1195 __ Call(ic, mode); | 1195 __ Call(ic, mode); |
1196 // Restore context register. | 1196 // Restore context register. |
1197 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1197 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1198 // Discard the function left on TOS. | 1198 // Discard the function left on TOS. |
1199 DropAndApply(1, context_, rax); | 1199 DropAndApply(1, context_, rax); |
1200 } | 1200 } |
1201 | 1201 |
1202 | 1202 |
1203 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1203 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
1204 // Code common for calls using the call stub. | 1204 // Code common for calls using the call stub. |
1205 ZoneList<Expression*>* args = expr->arguments(); | 1205 ZoneList<Expression*>* args = expr->arguments(); |
1206 int arg_count = args->length(); | 1206 int arg_count = args->length(); |
1207 for (int i = 0; i < arg_count; i++) { | 1207 for (int i = 0; i < arg_count; i++) { |
1208 VisitForValue(args->at(i), kStack); | 1208 VisitForValue(args->at(i), kStack); |
1209 } | 1209 } |
1210 // Record source position for debugger. | 1210 // Record source position for debugger. |
1211 SetSourcePosition(expr->position()); | 1211 SetSourcePosition(expr->position()); |
1212 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); | 1212 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
1213 __ CallStub(&stub); | 1213 __ CallStub(&stub); |
1214 // Restore context register. | 1214 // Restore context register. |
1215 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1215 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1216 // Discard the function left on TOS. | 1216 // Discard the function left on TOS. |
1217 DropAndApply(1, context_, rax); | 1217 DropAndApply(1, context_, rax); |
1218 } | 1218 } |
1219 | 1219 |
1220 | 1220 |
1221 void FastCodeGenerator::VisitCall(Call* expr) { | 1221 void FullCodeGenerator::VisitCall(Call* expr) { |
1222 Comment cmnt(masm_, "[ Call"); | 1222 Comment cmnt(masm_, "[ Call"); |
1223 Expression* fun = expr->expression(); | 1223 Expression* fun = expr->expression(); |
1224 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1224 Variable* var = fun->AsVariableProxy()->AsVariable(); |
1225 | 1225 |
1226 if (var != NULL && var->is_possibly_eval()) { | 1226 if (var != NULL && var->is_possibly_eval()) { |
1227 // Call to the identifier 'eval'. | 1227 // Call to the identifier 'eval'. |
1228 UNREACHABLE(); | 1228 UNREACHABLE(); |
1229 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1229 } else if (var != NULL && !var->is_this() && var->is_global()) { |
1230 // Call to a global variable. | 1230 // Call to a global variable. |
1231 __ Push(var->name()); | 1231 __ Push(var->name()); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1285 VisitForValue(fun, kStack); | 1285 VisitForValue(fun, kStack); |
1286 // Load global receiver object. | 1286 // Load global receiver object. |
1287 __ movq(rbx, CodeGenerator::GlobalObject()); | 1287 __ movq(rbx, CodeGenerator::GlobalObject()); |
1288 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | 1288 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); |
1289 // Emit function call. | 1289 // Emit function call. |
1290 EmitCallWithStub(expr); | 1290 EmitCallWithStub(expr); |
1291 } | 1291 } |
1292 } | 1292 } |
1293 | 1293 |
1294 | 1294 |
1295 void FastCodeGenerator::VisitCallNew(CallNew* expr) { | 1295 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
1296 Comment cmnt(masm_, "[ CallNew"); | 1296 Comment cmnt(masm_, "[ CallNew"); |
1297 // According to ECMA-262, section 11.2.2, page 44, the function | 1297 // According to ECMA-262, section 11.2.2, page 44, the function |
1298 // expression in new calls must be evaluated before the | 1298 // expression in new calls must be evaluated before the |
1299 // arguments. | 1299 // arguments. |
1300 // Push function on the stack. | 1300 // Push function on the stack. |
1301 VisitForValue(expr->expression(), kStack); | 1301 VisitForValue(expr->expression(), kStack); |
1302 | 1302 |
1303 // Push global object (receiver). | 1303 // Push global object (receiver). |
1304 __ push(CodeGenerator::GlobalObject()); | 1304 __ push(CodeGenerator::GlobalObject()); |
1305 | 1305 |
(...skipping 14 matching lines...) Expand all Loading... |
1320 __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); | 1320 __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); |
1321 | 1321 |
1322 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1322 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1323 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1323 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1324 | 1324 |
1325 // Replace function on TOS with result in rax, or pop it. | 1325 // Replace function on TOS with result in rax, or pop it. |
1326 DropAndApply(1, context_, rax); | 1326 DropAndApply(1, context_, rax); |
1327 } | 1327 } |
1328 | 1328 |
1329 | 1329 |
1330 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1330 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
1331 Comment cmnt(masm_, "[ CallRuntime"); | 1331 Comment cmnt(masm_, "[ CallRuntime"); |
1332 ZoneList<Expression*>* args = expr->arguments(); | 1332 ZoneList<Expression*>* args = expr->arguments(); |
1333 | 1333 |
1334 if (expr->is_jsruntime()) { | 1334 if (expr->is_jsruntime()) { |
1335 // Prepare for calling JS runtime function. | 1335 // Prepare for calling JS runtime function. |
1336 __ Push(expr->name()); | 1336 __ Push(expr->name()); |
1337 __ movq(rax, CodeGenerator::GlobalObject()); | 1337 __ movq(rax, CodeGenerator::GlobalObject()); |
1338 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); | 1338 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); |
1339 } | 1339 } |
1340 | 1340 |
(...skipping 12 matching lines...) Expand all Loading... |
1353 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1353 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1354 // Discard the function left on TOS. | 1354 // Discard the function left on TOS. |
1355 DropAndApply(1, context_, rax); | 1355 DropAndApply(1, context_, rax); |
1356 } else { | 1356 } else { |
1357 __ CallRuntime(expr->function(), arg_count); | 1357 __ CallRuntime(expr->function(), arg_count); |
1358 Apply(context_, rax); | 1358 Apply(context_, rax); |
1359 } | 1359 } |
1360 } | 1360 } |
1361 | 1361 |
1362 | 1362 |
1363 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1363 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
1364 switch (expr->op()) { | 1364 switch (expr->op()) { |
1365 case Token::VOID: { | 1365 case Token::VOID: { |
1366 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1366 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
1367 VisitForEffect(expr->expression()); | 1367 VisitForEffect(expr->expression()); |
1368 switch (context_) { | 1368 switch (context_) { |
1369 case Expression::kUninitialized: | 1369 case Expression::kUninitialized: |
1370 UNREACHABLE(); | 1370 UNREACHABLE(); |
1371 break; | 1371 break; |
1372 case Expression::kEffect: | 1372 case Expression::kEffect: |
1373 break; | 1373 break; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1463 Apply(context_, rax); | 1463 Apply(context_, rax); |
1464 break; | 1464 break; |
1465 } | 1465 } |
1466 | 1466 |
1467 default: | 1467 default: |
1468 UNREACHABLE(); | 1468 UNREACHABLE(); |
1469 } | 1469 } |
1470 } | 1470 } |
1471 | 1471 |
1472 | 1472 |
1473 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1473 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
1474 Comment cmnt(masm_, "[ CountOperation"); | 1474 Comment cmnt(masm_, "[ CountOperation"); |
1475 | 1475 |
1476 // Expression can only be a property, a global or a (parameter or local) | 1476 // Expression can only be a property, a global or a (parameter or local) |
1477 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1477 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1478 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1478 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1479 LhsKind assign_type = VARIABLE; | 1479 LhsKind assign_type = VARIABLE; |
1480 Property* prop = expr->expression()->AsProperty(); | 1480 Property* prop = expr->expression()->AsProperty(); |
1481 // In case of a property we use the uninitialized expression context | 1481 // In case of a property we use the uninitialized expression context |
1482 // of the key to detect a named property. | 1482 // of the key to detect a named property. |
1483 if (prop != NULL) { | 1483 if (prop != NULL) { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1594 ApplyTOS(context_); | 1594 ApplyTOS(context_); |
1595 } | 1595 } |
1596 } else { | 1596 } else { |
1597 DropAndApply(2, context_, rax); | 1597 DropAndApply(2, context_, rax); |
1598 } | 1598 } |
1599 break; | 1599 break; |
1600 } | 1600 } |
1601 } | 1601 } |
1602 } | 1602 } |
1603 | 1603 |
1604 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1604 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
1605 Comment cmnt(masm_, "[ BinaryOperation"); | 1605 Comment cmnt(masm_, "[ BinaryOperation"); |
1606 switch (expr->op()) { | 1606 switch (expr->op()) { |
1607 case Token::COMMA: | 1607 case Token::COMMA: |
1608 VisitForEffect(expr->left()); | 1608 VisitForEffect(expr->left()); |
1609 Visit(expr->right()); | 1609 Visit(expr->right()); |
1610 break; | 1610 break; |
1611 | 1611 |
1612 case Token::OR: | 1612 case Token::OR: |
1613 case Token::AND: | 1613 case Token::AND: |
1614 EmitLogicalOperation(expr); | 1614 EmitLogicalOperation(expr); |
(...skipping 14 matching lines...) Expand all Loading... |
1629 VisitForValue(expr->right(), kAccumulator); | 1629 VisitForValue(expr->right(), kAccumulator); |
1630 EmitBinaryOp(expr->op(), context_); | 1630 EmitBinaryOp(expr->op(), context_); |
1631 break; | 1631 break; |
1632 | 1632 |
1633 default: | 1633 default: |
1634 UNREACHABLE(); | 1634 UNREACHABLE(); |
1635 } | 1635 } |
1636 } | 1636 } |
1637 | 1637 |
1638 | 1638 |
1639 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1639 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
1640 Comment cmnt(masm_, "[ CompareOperation"); | 1640 Comment cmnt(masm_, "[ CompareOperation"); |
1641 | 1641 |
1642 // Always perform the comparison for its control flow. Pack the result | 1642 // Always perform the comparison for its control flow. Pack the result |
1643 // into the expression's context after the comparison is performed. | 1643 // into the expression's context after the comparison is performed. |
1644 Label materialize_true, materialize_false, done; | 1644 Label materialize_true, materialize_false, done; |
1645 // Initially assume we are in a test context. | 1645 // Initially assume we are in a test context. |
1646 Label* if_true = true_label_; | 1646 Label* if_true = true_label_; |
1647 Label* if_false = false_label_; | 1647 Label* if_false = false_label_; |
1648 switch (context_) { | 1648 switch (context_) { |
1649 case Expression::kUninitialized: | 1649 case Expression::kUninitialized: |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1741 __ jmp(if_false); | 1741 __ jmp(if_false); |
1742 } | 1742 } |
1743 } | 1743 } |
1744 | 1744 |
1745 // Convert the result of the comparison into one expected for this | 1745 // Convert the result of the comparison into one expected for this |
1746 // expression's context. | 1746 // expression's context. |
1747 Apply(context_, if_true, if_false); | 1747 Apply(context_, if_true, if_false); |
1748 } | 1748 } |
1749 | 1749 |
1750 | 1750 |
1751 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1751 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
1752 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1752 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
1753 Apply(context_, rax); | 1753 Apply(context_, rax); |
1754 } | 1754 } |
1755 | 1755 |
1756 | 1756 |
1757 Register FastCodeGenerator::result_register() { return rax; } | 1757 Register FullCodeGenerator::result_register() { return rax; } |
1758 | 1758 |
1759 | 1759 |
1760 Register FastCodeGenerator::context_register() { return rsi; } | 1760 Register FullCodeGenerator::context_register() { return rsi; } |
1761 | 1761 |
1762 | 1762 |
1763 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1763 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
1764 ASSERT(IsAligned(frame_offset, kPointerSize)); | 1764 ASSERT(IsAligned(frame_offset, kPointerSize)); |
1765 __ movq(Operand(rbp, frame_offset), value); | 1765 __ movq(Operand(rbp, frame_offset), value); |
1766 } | 1766 } |
1767 | 1767 |
1768 | 1768 |
1769 void FastCodeGenerator::LoadContextField(Register dst, int context_index) { | 1769 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
1770 __ movq(dst, CodeGenerator::ContextOperand(rsi, context_index)); | 1770 __ movq(dst, CodeGenerator::ContextOperand(rsi, context_index)); |
1771 } | 1771 } |
1772 | 1772 |
1773 | 1773 |
1774 // ---------------------------------------------------------------------------- | 1774 // ---------------------------------------------------------------------------- |
1775 // Non-local control flow support. | 1775 // Non-local control flow support. |
1776 | 1776 |
1777 | 1777 |
1778 void FastCodeGenerator::EnterFinallyBlock() { | 1778 void FullCodeGenerator::EnterFinallyBlock() { |
1779 ASSERT(!result_register().is(rdx)); | 1779 ASSERT(!result_register().is(rdx)); |
1780 ASSERT(!result_register().is(rcx)); | 1780 ASSERT(!result_register().is(rcx)); |
1781 // Cook return address on top of stack (smi encoded Code* delta) | 1781 // Cook return address on top of stack (smi encoded Code* delta) |
1782 __ movq(rdx, Operand(rsp, 0)); | 1782 __ movq(rdx, Operand(rsp, 0)); |
1783 __ Move(rcx, masm_->CodeObject()); | 1783 __ Move(rcx, masm_->CodeObject()); |
1784 __ subq(rdx, rcx); | 1784 __ subq(rdx, rcx); |
1785 __ Integer32ToSmi(rdx, rdx); | 1785 __ Integer32ToSmi(rdx, rdx); |
1786 __ movq(Operand(rsp, 0), rdx); | 1786 __ movq(Operand(rsp, 0), rdx); |
1787 // Store result register while executing finally block. | 1787 // Store result register while executing finally block. |
1788 __ push(result_register()); | 1788 __ push(result_register()); |
1789 } | 1789 } |
1790 | 1790 |
1791 | 1791 |
1792 void FastCodeGenerator::ExitFinallyBlock() { | 1792 void FullCodeGenerator::ExitFinallyBlock() { |
1793 ASSERT(!result_register().is(rdx)); | 1793 ASSERT(!result_register().is(rdx)); |
1794 ASSERT(!result_register().is(rcx)); | 1794 ASSERT(!result_register().is(rcx)); |
1795 // Restore result register from stack. | 1795 // Restore result register from stack. |
1796 __ pop(result_register()); | 1796 __ pop(result_register()); |
1797 // Uncook return address. | 1797 // Uncook return address. |
1798 __ movq(rdx, Operand(rsp, 0)); | 1798 __ movq(rdx, Operand(rsp, 0)); |
1799 __ SmiToInteger32(rdx, rdx); | 1799 __ SmiToInteger32(rdx, rdx); |
1800 __ Move(rcx, masm_->CodeObject()); | 1800 __ Move(rcx, masm_->CodeObject()); |
1801 __ addq(rdx, rcx); | 1801 __ addq(rdx, rcx); |
1802 __ movq(Operand(rsp, 0), rdx); | 1802 __ movq(Operand(rsp, 0), rdx); |
1803 // And return. | 1803 // And return. |
1804 __ ret(0); | 1804 __ ret(0); |
1805 } | 1805 } |
1806 | 1806 |
1807 | 1807 |
1808 #undef __ | 1808 #undef __ |
1809 | 1809 |
1810 | 1810 |
1811 } } // namespace v8::internal | 1811 } } // namespace v8::internal |
OLD | NEW |