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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 2121014: Revert change 3849. On ia32, LoadFromSlot again returns its result on the to... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 7 months 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.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 677 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 // <global>.<variable> and perform a (regular non-contextual) property 688 // <global>.<variable> and perform a (regular non-contextual) property
689 // load to make sure we do not get reference errors. 689 // load to make sure we do not get reference errors.
690 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); 690 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
691 Literal key(variable->name()); 691 Literal key(variable->name());
692 Property property(&global, &key, RelocInfo::kNoPosition); 692 Property property(&global, &key, RelocInfo::kNoPosition);
693 Reference ref(this, &property); 693 Reference ref(this, &property);
694 ref.GetValue(); 694 ref.GetValue();
695 } else if (variable != NULL && variable->slot() != NULL) { 695 } else if (variable != NULL && variable->slot() != NULL) {
696 // For a variable that rewrites to a slot, we signal it is the immediate 696 // For a variable that rewrites to a slot, we signal it is the immediate
697 // subexpression of a typeof. 697 // subexpression of a typeof.
698 Result result = 698 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF);
699 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF);
700 frame()->Push(&result);
701 } else { 699 } else {
702 // Anything else can be handled normally. 700 // Anything else can be handled normally.
703 Load(expr); 701 Load(expr);
704 } 702 }
705 } 703 }
706 704
707 705
708 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { 706 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
709 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; 707 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
710 ASSERT(scope()->arguments_shadow() != NULL); 708 ASSERT(scope()->arguments_shadow() != NULL);
(...skipping 28 matching lines...) Expand all
739 Variable* arguments = scope()->arguments()->var(); 737 Variable* arguments = scope()->arguments()->var();
740 Variable* shadow = scope()->arguments_shadow()->var(); 738 Variable* shadow = scope()->arguments_shadow()->var();
741 ASSERT(arguments != NULL && arguments->slot() != NULL); 739 ASSERT(arguments != NULL && arguments->slot() != NULL);
742 ASSERT(shadow != NULL && shadow->slot() != NULL); 740 ASSERT(shadow != NULL && shadow->slot() != NULL);
743 JumpTarget done; 741 JumpTarget done;
744 bool skip_arguments = false; 742 bool skip_arguments = false;
745 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { 743 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
746 // We have to skip storing into the arguments slot if it has already 744 // We have to skip storing into the arguments slot if it has already
747 // been written to. This can happen if the a function has a local 745 // been written to. This can happen if the a function has a local
748 // variable named 'arguments'. 746 // variable named 'arguments'.
749 Result probe = LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF); 747 LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF);
748 Result probe = frame_->Pop();
750 if (probe.is_constant()) { 749 if (probe.is_constant()) {
751 // We have to skip updating the arguments object if it has 750 // We have to skip updating the arguments object if it has
752 // been assigned a proper value. 751 // been assigned a proper value.
753 skip_arguments = !probe.handle()->IsTheHole(); 752 skip_arguments = !probe.handle()->IsTheHole();
754 } else { 753 } else {
755 __ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value())); 754 __ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value()));
756 probe.Unuse(); 755 probe.Unuse();
757 done.Branch(not_equal); 756 done.Branch(not_equal);
758 } 757 }
759 } 758 }
(...skipping 2259 matching lines...) Expand 10 before | Expand all | Expand 10 after
3019 frame()->Dup(); 3018 frame()->Dup();
3020 Handle<String> name = Factory::LookupAsciiSymbol("apply"); 3019 Handle<String> name = Factory::LookupAsciiSymbol("apply");
3021 frame()->Push(name); 3020 frame()->Push(name);
3022 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); 3021 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET);
3023 __ nop(); 3022 __ nop();
3024 frame()->Push(&answer); 3023 frame()->Push(&answer);
3025 3024
3026 // Load the receiver and the existing arguments object onto the 3025 // Load the receiver and the existing arguments object onto the
3027 // expression stack. Avoid allocating the arguments object here. 3026 // expression stack. Avoid allocating the arguments object here.
3028 Load(receiver); 3027 Load(receiver);
3029 Result existing_args = 3028 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
3030 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
3031 frame()->Push(&existing_args);
3032 3029
3033 // Emit the source position information after having loaded the 3030 // Emit the source position information after having loaded the
3034 // receiver and the arguments. 3031 // receiver and the arguments.
3035 CodeForSourcePosition(position); 3032 CodeForSourcePosition(position);
3036 // Contents of frame at this point: 3033 // Contents of frame at this point:
3037 // Frame[0]: arguments object of the current function or the hole. 3034 // Frame[0]: arguments object of the current function or the hole.
3038 // Frame[1]: receiver 3035 // Frame[1]: receiver
3039 // Frame[2]: applicand.apply 3036 // Frame[2]: applicand.apply
3040 // Frame[3]: applicand. 3037 // Frame[3]: applicand.
3041 3038
(...skipping 1670 matching lines...) Expand 10 before | Expand all | Expand 10 after
4712 exit.Jump(); 4709 exit.Jump();
4713 else_.Bind(); 4710 else_.Bind();
4714 Load(node->else_expression()); 4711 Load(node->else_expression());
4715 } 4712 }
4716 } 4713 }
4717 4714
4718 exit.Bind(); 4715 exit.Bind();
4719 } 4716 }
4720 4717
4721 4718
4722 Result CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 4719 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
4723 Result result;
4724 if (slot->type() == Slot::LOOKUP) { 4720 if (slot->type() == Slot::LOOKUP) {
4725 ASSERT(slot->var()->is_dynamic()); 4721 ASSERT(slot->var()->is_dynamic());
4726 JumpTarget slow; 4722 JumpTarget slow;
4727 JumpTarget done; 4723 JumpTarget done;
4724 Result value;
4728 4725
4729 // Generate fast case for loading from slots that correspond to 4726 // Generate fast case for loading from slots that correspond to
4730 // local/global variables or arguments unless they are shadowed by 4727 // local/global variables or arguments unless they are shadowed by
4731 // eval-introduced bindings. 4728 // eval-introduced bindings.
4732 EmitDynamicLoadFromSlotFastCase(slot, 4729 EmitDynamicLoadFromSlotFastCase(slot,
4733 typeof_state, 4730 typeof_state,
4734 &result, 4731 &value,
4735 &slow, 4732 &slow,
4736 &done); 4733 &done);
4737 4734
4738 slow.Bind(); 4735 slow.Bind();
4739 // A runtime call is inevitable. We eagerly sync frame elements 4736 // A runtime call is inevitable. We eagerly sync frame elements
4740 // to memory so that we can push the arguments directly into place 4737 // to memory so that we can push the arguments directly into place
4741 // on top of the frame. 4738 // on top of the frame.
4742 frame()->SyncRange(0, frame()->element_count() - 1); 4739 frame()->SyncRange(0, frame()->element_count() - 1);
4743 frame()->EmitPush(esi); 4740 frame()->EmitPush(esi);
4744 frame()->EmitPush(Immediate(slot->var()->name())); 4741 frame()->EmitPush(Immediate(slot->var()->name()));
4745 if (typeof_state == INSIDE_TYPEOF) { 4742 if (typeof_state == INSIDE_TYPEOF) {
4746 result = 4743 value =
4747 frame()->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 4744 frame()->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
4748 } else { 4745 } else {
4749 result = frame()->CallRuntime(Runtime::kLoadContextSlot, 2); 4746 value = frame()->CallRuntime(Runtime::kLoadContextSlot, 2);
4750 } 4747 }
4751 4748
4752 done.Bind(&result); 4749 done.Bind(&value);
4753 return result; 4750 frame_->Push(&value);
4754 4751
4755 } else if (slot->var()->mode() == Variable::CONST) { 4752 } else if (slot->var()->mode() == Variable::CONST) {
4756 // Const slots may contain 'the hole' value (the constant hasn't been 4753 // Const slots may contain 'the hole' value (the constant hasn't been
4757 // initialized yet) which needs to be converted into the 'undefined' 4754 // initialized yet) which needs to be converted into the 'undefined'
4758 // value. 4755 // value.
4759 // 4756 //
4760 // We currently spill the virtual frame because constants use the 4757 // We currently spill the virtual frame because constants use the
4761 // potentially unsafe direct-frame access of SlotOperand. 4758 // potentially unsafe direct-frame access of SlotOperand.
4762 VirtualFrame::SpilledScope spilled_scope; 4759 VirtualFrame::SpilledScope spilled_scope;
4763 Comment cmnt(masm_, "[ Load const"); 4760 Comment cmnt(masm_, "[ Load const");
4764 Label exit; 4761 Label exit;
4765 __ mov(ecx, SlotOperand(slot, ecx)); 4762 __ mov(ecx, SlotOperand(slot, ecx));
4766 __ cmp(ecx, Factory::the_hole_value()); 4763 __ cmp(ecx, Factory::the_hole_value());
4767 __ j(not_equal, &exit); 4764 __ j(not_equal, &exit);
4768 __ mov(ecx, Factory::undefined_value()); 4765 __ mov(ecx, Factory::undefined_value());
4769 __ bind(&exit); 4766 __ bind(&exit);
4770 return Result(ecx); 4767 frame()->EmitPush(ecx);
4771 4768
4772 } else if (slot->type() == Slot::PARAMETER) { 4769 } else if (slot->type() == Slot::PARAMETER) {
4773 frame()->PushParameterAt(slot->index()); 4770 frame()->PushParameterAt(slot->index());
4774 return frame()->Pop();
4775 4771
4776 } else if (slot->type() == Slot::LOCAL) { 4772 } else if (slot->type() == Slot::LOCAL) {
4777 frame()->PushLocalAt(slot->index()); 4773 frame()->PushLocalAt(slot->index());
4778 return frame()->Pop();
4779 4774
4780 } else { 4775 } else {
4781 // The other remaining slot types (LOOKUP and GLOBAL) cannot reach 4776 // The other remaining slot types (LOOKUP and GLOBAL) cannot reach
4782 // here. 4777 // here.
4783 // 4778 //
4784 // The use of SlotOperand below is safe for an unspilled frame 4779 // The use of SlotOperand below is safe for an unspilled frame
4785 // because it will always be a context slot. 4780 // because it will always be a context slot.
4786 ASSERT(slot->type() == Slot::CONTEXT); 4781 ASSERT(slot->type() == Slot::CONTEXT);
4787 result = allocator()->Allocate(); 4782 Result temp = allocator()->Allocate();
4788 ASSERT(result.is_valid()); 4783 ASSERT(temp.is_valid());
4789 __ mov(result.reg(), SlotOperand(slot, result.reg())); 4784 __ mov(temp.reg(), SlotOperand(slot, temp.reg()));
4790 return result; 4785 frame()->Push(&temp);
4791 } 4786 }
4792 } 4787 }
4793 4788
4794 4789
4795 Result CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot, 4790 void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot,
4796 TypeofState state) { 4791 TypeofState state) {
William Hesse 2010/05/21 11:49:57 Will fix indentation here.
4797 Result result = LoadFromSlot(slot, state); 4792 LoadFromSlot(slot, state);
4798 4793
4799 // Bail out quickly if we're not using lazy arguments allocation. 4794 // Bail out quickly if we're not using lazy arguments allocation.
4800 if (ArgumentsMode() != LAZY_ARGUMENTS_ALLOCATION) return result; 4795 if (ArgumentsMode() != LAZY_ARGUMENTS_ALLOCATION) return;
4801 4796
4802 // ... or if the slot isn't a non-parameter arguments slot. 4797 // ... or if the slot isn't a non-parameter arguments slot.
4803 if (slot->type() == Slot::PARAMETER || !slot->is_arguments()) return result; 4798 if (slot->type() == Slot::PARAMETER || !slot->is_arguments()) return;
4804 4799
4805 // If the loaded value is a constant, we know if the arguments 4800 // If the loaded value is a constant, we know if the arguments
4806 // object has been lazily loaded yet. 4801 // object has been lazily loaded yet.
4802 Result result = frame()->Pop();
4807 if (result.is_constant()) { 4803 if (result.is_constant()) {
4808 if (result.handle()->IsTheHole()) { 4804 if (result.handle()->IsTheHole()) {
4809 result.Unuse(); 4805 result = StoreArgumentsObject(false);
4810 return StoreArgumentsObject(false);
4811 } else {
4812 return result;
4813 } 4806 }
4807 frame()->Push(&result);
4808 return;
4814 } 4809 }
4815 4810 ASSERT(result.is_register());
4816 // The loaded value is in a register. If it is the sentinel that 4811 // The loaded value is in a register. If it is the sentinel that
4817 // indicates that we haven't loaded the arguments object yet, we 4812 // indicates that we haven't loaded the arguments object yet, we
4818 // need to do it now. 4813 // need to do it now.
4819 JumpTarget exit; 4814 JumpTarget exit;
4820 __ cmp(Operand(result.reg()), Immediate(Factory::the_hole_value())); 4815 __ cmp(Operand(result.reg()), Immediate(Factory::the_hole_value()));
4821 exit.Branch(not_equal, &result); 4816 frame()->Push(&result);
4817 exit.Branch(not_equal);
4822 4818
4819 result = StoreArgumentsObject(false);
4820 frame()->SetElementAt(0, &result);
4823 result.Unuse(); 4821 result.Unuse();
4824 result = StoreArgumentsObject(false); 4822 exit.Bind();
4825 exit.Bind(&result); 4823 return;
4826 return result;
4827 } 4824 }
4828 4825
4829 4826
4830 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( 4827 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
4831 Slot* slot, 4828 Slot* slot,
4832 TypeofState typeof_state, 4829 TypeofState typeof_state,
4833 JumpTarget* slow) { 4830 JumpTarget* slow) {
4834 ASSERT(!in_safe_int32_mode()); 4831 ASSERT(!in_safe_int32_mode());
4835 // Check that no extension objects have been created by calls to 4832 // Check that no extension objects have been created by calls to
4836 // eval from the current scope to the global scope. 4833 // eval from the current scope to the global scope.
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
5066 Comment cmnt(masm_, "[ Slot"); 5063 Comment cmnt(masm_, "[ Slot");
5067 if (in_safe_int32_mode()) { 5064 if (in_safe_int32_mode()) {
5068 if ((slot->type() == Slot::LOCAL && !slot->is_arguments())) { 5065 if ((slot->type() == Slot::LOCAL && !slot->is_arguments())) {
5069 frame()->UntaggedPushLocalAt(slot->index()); 5066 frame()->UntaggedPushLocalAt(slot->index());
5070 } else if (slot->type() == Slot::PARAMETER) { 5067 } else if (slot->type() == Slot::PARAMETER) {
5071 frame()->UntaggedPushParameterAt(slot->index()); 5068 frame()->UntaggedPushParameterAt(slot->index());
5072 } else { 5069 } else {
5073 UNREACHABLE(); 5070 UNREACHABLE();
5074 } 5071 }
5075 } else { 5072 } else {
5076 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); 5073 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
5077 frame()->Push(&result);
5078 } 5074 }
5079 } 5075 }
5080 5076
5081 5077
5082 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 5078 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
5083 Comment cmnt(masm_, "[ VariableProxy"); 5079 Comment cmnt(masm_, "[ VariableProxy");
5084 Variable* var = node->var(); 5080 Variable* var = node->var();
5085 Expression* expr = var->rewrite(); 5081 Expression* expr = var->rewrite();
5086 if (expr != NULL) { 5082 if (expr != NULL) {
5087 Visit(expr); 5083 Visit(expr);
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
5388 Comment cmnt(masm(), "[ Variable Assignment"); 5384 Comment cmnt(masm(), "[ Variable Assignment");
5389 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 5385 Variable* var = node->target()->AsVariableProxy()->AsVariable();
5390 ASSERT(var != NULL); 5386 ASSERT(var != NULL);
5391 Slot* slot = var->slot(); 5387 Slot* slot = var->slot();
5392 ASSERT(slot != NULL); 5388 ASSERT(slot != NULL);
5393 5389
5394 // Evaluate the right-hand side. 5390 // Evaluate the right-hand side.
5395 if (node->is_compound()) { 5391 if (node->is_compound()) {
5396 // For a compound assignment the right-hand side is a binary operation 5392 // For a compound assignment the right-hand side is a binary operation
5397 // between the current property value and the actual right-hand side. 5393 // between the current property value and the actual right-hand side.
5398 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); 5394 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
5399 frame()->Push(&result);
5400 Load(node->value()); 5395 Load(node->value());
5401 5396
5402 // Perform the binary operation. 5397 // Perform the binary operation.
5403 bool overwrite_value = 5398 bool overwrite_value =
5404 (node->value()->AsBinaryOperation() != NULL && 5399 (node->value()->AsBinaryOperation() != NULL &&
5405 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 5400 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
5406 // Construct the implicit binary operation. 5401 // Construct the implicit binary operation.
5407 BinaryOperation expr(node, node->binary_op(), node->target(), 5402 BinaryOperation expr(node, node->binary_op(), node->target(),
5408 node->value()); 5403 node->value());
5409 GenericBinaryOperation(&expr, 5404 GenericBinaryOperation(&expr,
(...skipping 3440 matching lines...) Expand 10 before | Expand all | Expand 10 after
8850 Property* property = expression_->AsProperty(); 8845 Property* property = expression_->AsProperty();
8851 if (property != NULL) { 8846 if (property != NULL) {
8852 cgen_->CodeForSourcePosition(property->position()); 8847 cgen_->CodeForSourcePosition(property->position());
8853 } 8848 }
8854 8849
8855 switch (type_) { 8850 switch (type_) {
8856 case SLOT: { 8851 case SLOT: {
8857 Comment cmnt(masm, "[ Load from Slot"); 8852 Comment cmnt(masm, "[ Load from Slot");
8858 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 8853 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
8859 ASSERT(slot != NULL); 8854 ASSERT(slot != NULL);
8860 Result result = 8855 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
8861 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
8862 if (!persist_after_get_) set_unloaded(); 8856 if (!persist_after_get_) set_unloaded();
8863 cgen_->frame()->Push(&result);
8864 break; 8857 break;
8865 } 8858 }
8866 8859
8867 case NAMED: { 8860 case NAMED: {
8868 Variable* var = expression_->AsVariableProxy()->AsVariable(); 8861 Variable* var = expression_->AsVariableProxy()->AsVariable();
8869 bool is_global = var != NULL; 8862 bool is_global = var != NULL;
8870 ASSERT(!is_global || var->is_global()); 8863 ASSERT(!is_global || var->is_global());
8871 if (persist_after_get_) cgen_->frame()->Dup(); 8864 if (persist_after_get_) cgen_->frame()->Dup();
8872 Result result = cgen_->EmitNamedLoad(GetName(), is_global); 8865 Result result = cgen_->EmitNamedLoad(GetName(), is_global);
8873 if (!persist_after_get_) set_unloaded(); 8866 if (!persist_after_get_) set_unloaded();
(...skipping 4418 matching lines...) Expand 10 before | Expand all | Expand 10 after
13292 // tagged as a small integer. 13285 // tagged as a small integer.
13293 __ bind(&runtime); 13286 __ bind(&runtime);
13294 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 13287 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
13295 } 13288 }
13296 13289
13297 #undef __ 13290 #undef __
13298 13291
13299 } } // namespace v8::internal 13292 } } // namespace v8::internal
13300 13293
13301 #endif // V8_TARGET_ARCH_IA32 13294 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698