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 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 __ push(Immediate(boilerplate)); | 403 __ push(Immediate(boilerplate)); |
404 __ CallRuntime(Runtime::kNewClosure, 2); | 404 __ CallRuntime(Runtime::kNewClosure, 2); |
405 Move(expr->context(), eax); | 405 Move(expr->context(), eax); |
406 } | 406 } |
407 | 407 |
408 | 408 |
409 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 409 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
410 Comment cmnt(masm_, "[ VariableProxy"); | 410 Comment cmnt(masm_, "[ VariableProxy"); |
411 Expression* rewrite = expr->var()->rewrite(); | 411 Expression* rewrite = expr->var()->rewrite(); |
412 if (rewrite == NULL) { | 412 if (rewrite == NULL) { |
| 413 ASSERT(expr->var()->is_global()); |
413 Comment cmnt(masm_, "Global variable"); | 414 Comment cmnt(masm_, "Global variable"); |
414 // Use inline caching. Variable name is passed in ecx and the global | 415 // Use inline caching. Variable name is passed in ecx and the global |
415 // object on the stack. | 416 // object on the stack. |
416 __ push(CodeGenerator::GlobalObject()); | 417 __ push(CodeGenerator::GlobalObject()); |
417 __ mov(ecx, expr->name()); | 418 __ mov(ecx, expr->name()); |
418 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 419 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
419 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 420 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
420 // By emitting a nop we make sure that we do not have a test eax | 421 // By emitting a nop we make sure that we do not have a test eax |
421 // instruction after the call it is treated specially by the LoadIC code | 422 // instruction after the call it is treated specially by the LoadIC code |
422 // Remember that the assembler may choose to do peephole optimization | 423 // Remember that the assembler may choose to do peephole optimization |
423 // (eg, push/pop elimination). | 424 // (eg, push/pop elimination). |
424 __ nop(); | 425 __ nop(); |
425 | 426 |
426 DropAndMove(expr->context(), eax); | 427 DropAndMove(expr->context(), eax); |
427 } else { | 428 } else { |
428 Comment cmnt(masm_, "Stack slot"); | 429 Slot* slot = rewrite->AsSlot(); |
429 Move(expr->context(), rewrite->AsSlot()); | 430 ASSERT_NE(NULL, slot); |
| 431 switch (slot->type()) { |
| 432 case Slot::LOCAL: |
| 433 case Slot::PARAMETER: { |
| 434 Comment cmnt(masm_, "Stack slot"); |
| 435 Move(expr->context(), slot); |
| 436 break; |
| 437 } |
| 438 |
| 439 case Slot::CONTEXT: { |
| 440 Comment cmnt(masm_, "Context slot"); |
| 441 int chain_length = |
| 442 function_->scope()->ContextChainLength(slot->var()->scope()); |
| 443 if (chain_length > 0) { |
| 444 // Move up the chain of contexts to the context containing the slot. |
| 445 __ mov(eax, |
| 446 Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX))); |
| 447 // Load the function context (which is the incoming, outer context). |
| 448 __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); |
| 449 for (int i = 1; i < chain_length; i++) { |
| 450 __ mov(eax, |
| 451 Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX))); |
| 452 __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); |
| 453 } |
| 454 // The context may be an intermediate context, not a function context. |
| 455 __ mov(eax, |
| 456 Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
| 457 } else { // Slot is in the current function context. |
| 458 // The context may be an intermediate context, not a function context. |
| 459 __ mov(eax, |
| 460 Operand(esi, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
| 461 } |
| 462 __ mov(eax, Operand(eax, Context::SlotOffset(slot->index()))); |
| 463 Move(expr->context(), eax); |
| 464 break; |
| 465 } |
| 466 |
| 467 case Slot::LOOKUP: |
| 468 UNREACHABLE(); |
| 469 break; |
| 470 } |
430 } | 471 } |
431 } | 472 } |
432 | 473 |
433 | 474 |
434 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 475 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
435 Comment cmnt(masm_, "[ RegExpLiteral"); | 476 Comment cmnt(masm_, "[ RegExpLiteral"); |
436 Label done; | 477 Label done; |
437 // Registers will be used as follows: | 478 // Registers will be used as follows: |
438 // edi = JS function. | 479 // edi = JS function. |
439 // ebx = literals array. | 480 // ebx = literals array. |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 // ecx, and the global object on the stack. | 727 // ecx, and the global object on the stack. |
687 __ pop(eax); | 728 __ pop(eax); |
688 __ mov(ecx, var->name()); | 729 __ mov(ecx, var->name()); |
689 __ push(CodeGenerator::GlobalObject()); | 730 __ push(CodeGenerator::GlobalObject()); |
690 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 731 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
691 __ call(ic, RelocInfo::CODE_TARGET); | 732 __ call(ic, RelocInfo::CODE_TARGET); |
692 // Overwrite the receiver on the stack with the result if needed. | 733 // Overwrite the receiver on the stack with the result if needed. |
693 DropAndMove(expr->context(), eax); | 734 DropAndMove(expr->context(), eax); |
694 | 735 |
695 } else { | 736 } else { |
696 switch (expr->context()) { | 737 Slot* slot = var->slot(); |
697 case Expression::kUninitialized: | 738 ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled. |
698 UNREACHABLE(); | 739 switch (slot->type()) { |
699 case Expression::kEffect: | 740 case Slot::LOCAL: |
700 // Perform assignment and discard value. | 741 case Slot::PARAMETER: { |
701 __ pop(Operand(ebp, SlotOffset(var->slot()))); | 742 switch (expr->context()) { |
702 break; | 743 case Expression::kUninitialized: |
703 case Expression::kValue: | 744 UNREACHABLE(); |
704 // Perform assignment and preserve value. | 745 case Expression::kEffect: |
705 __ mov(eax, Operand(esp, 0)); | 746 // Perform assignment and discard value. |
706 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); | 747 __ pop(Operand(ebp, SlotOffset(var->slot()))); |
707 break; | 748 break; |
708 case Expression::kTest: | 749 case Expression::kValue: |
709 // Perform assignment and test (and discard) value. | 750 // Perform assignment and preserve value. |
710 __ pop(eax); | 751 __ mov(eax, Operand(esp, 0)); |
711 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); | 752 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
712 TestAndBranch(eax, true_label_, false_label_); | 753 break; |
713 break; | 754 case Expression::kTest: |
714 case Expression::kValueTest: { | 755 // Perform assignment and test (and discard) value. |
715 Label discard; | 756 __ pop(eax); |
716 __ mov(eax, Operand(esp, 0)); | 757 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
717 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); | 758 TestAndBranch(eax, true_label_, false_label_); |
718 TestAndBranch(eax, true_label_, &discard); | 759 break; |
719 __ bind(&discard); | 760 case Expression::kValueTest: { |
720 __ add(Operand(esp), Immediate(kPointerSize)); | 761 Label discard; |
721 __ jmp(false_label_); | 762 __ mov(eax, Operand(esp, 0)); |
| 763 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
| 764 TestAndBranch(eax, true_label_, &discard); |
| 765 __ bind(&discard); |
| 766 __ add(Operand(esp), Immediate(kPointerSize)); |
| 767 __ jmp(false_label_); |
| 768 break; |
| 769 } |
| 770 case Expression::kTestValue: { |
| 771 Label discard; |
| 772 __ mov(eax, Operand(esp, 0)); |
| 773 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
| 774 TestAndBranch(eax, &discard, false_label_); |
| 775 __ bind(&discard); |
| 776 __ add(Operand(esp), Immediate(kPointerSize)); |
| 777 __ jmp(true_label_); |
| 778 break; |
| 779 } |
| 780 } |
722 break; | 781 break; |
723 } | 782 } |
724 case Expression::kTestValue: { | 783 |
725 Label discard; | 784 case Slot::CONTEXT: { |
726 __ mov(eax, Operand(esp, 0)); | 785 int chain_length = |
727 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); | 786 function_->scope()->ContextChainLength(slot->var()->scope()); |
728 TestAndBranch(eax, &discard, false_label_); | 787 if (chain_length > 0) { |
729 __ bind(&discard); | 788 // Move up the context chain to the context containing the slot. |
730 __ add(Operand(esp), Immediate(kPointerSize)); | 789 __ mov(eax, |
731 __ jmp(true_label_); | 790 Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX))); |
| 791 // Load the function context (which is the incoming, outer context). |
| 792 __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); |
| 793 for (int i = 1; i < chain_length; i++) { |
| 794 __ mov(eax, |
| 795 Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX))); |
| 796 __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); |
| 797 } |
| 798 } else { // Slot is in the current context. Generate optimized code. |
| 799 __ mov(eax, esi); // RecordWrite destroys the object register. |
| 800 } |
| 801 if (FLAG_debug_code) { |
| 802 __ cmp(eax, |
| 803 Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
| 804 __ Check(equal, "Context Slot chain length wrong."); |
| 805 } |
| 806 __ pop(ecx); |
| 807 __ mov(Operand(eax, Context::SlotOffset(slot->index())), ecx); |
| 808 |
| 809 // RecordWrite may destroy all its register arguments. |
| 810 if (expr->context() == Expression::kValue) { |
| 811 __ push(ecx); |
| 812 } else if (expr->context() != Expression::kEffect) { |
| 813 __ mov(edx, ecx); |
| 814 } |
| 815 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 816 __ RecordWrite(eax, offset, ecx, ebx); |
| 817 if (expr->context() != Expression::kEffect && |
| 818 expr->context() != Expression::kValue) { |
| 819 Move(expr->context(), edx); |
| 820 } |
732 break; | 821 break; |
733 } | 822 } |
| 823 |
| 824 case Slot::LOOKUP: |
| 825 UNREACHABLE(); |
| 826 break; |
734 } | 827 } |
735 } | 828 } |
736 } | 829 } |
737 | 830 |
738 | 831 |
739 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 832 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
740 // Assignment to a property, using a named store IC. | 833 // Assignment to a property, using a named store IC. |
741 Property* prop = expr->target()->AsProperty(); | 834 Property* prop = expr->target()->AsProperty(); |
742 ASSERT(prop != NULL); | 835 ASSERT(prop != NULL); |
743 ASSERT(prop->key()->AsLiteral() != NULL); | 836 ASSERT(prop->key()->AsLiteral() != NULL); |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1409 true_label_ = saved_true; | 1502 true_label_ = saved_true; |
1410 false_label_ = saved_false; | 1503 false_label_ = saved_false; |
1411 // Convert current context to test context: End post-test code. | 1504 // Convert current context to test context: End post-test code. |
1412 } | 1505 } |
1413 | 1506 |
1414 | 1507 |
1415 #undef __ | 1508 #undef __ |
1416 | 1509 |
1417 | 1510 |
1418 } } // namespace v8::internal | 1511 } } // namespace v8::internal |
OLD | NEW |