Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 567 // <global>.<variable> and perform a (regular non-contextual) property | 567 // <global>.<variable> and perform a (regular non-contextual) property |
| 568 // load to make sure we do not get reference errors. | 568 // load to make sure we do not get reference errors. |
| 569 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 569 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); |
| 570 Literal key(variable->name()); | 570 Literal key(variable->name()); |
| 571 Property property(&global, &key, RelocInfo::kNoPosition); | 571 Property property(&global, &key, RelocInfo::kNoPosition); |
| 572 Reference ref(this, &property); | 572 Reference ref(this, &property); |
| 573 ref.GetValue(); | 573 ref.GetValue(); |
| 574 } else if (variable != NULL && variable->slot() != NULL) { | 574 } else if (variable != NULL && variable->slot() != NULL) { |
| 575 // For a variable that rewrites to a slot, we signal it is the immediate | 575 // For a variable that rewrites to a slot, we signal it is the immediate |
| 576 // subexpression of a typeof. | 576 // subexpression of a typeof. |
| 577 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); | 577 Result result = |
| 578 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); | |
| 579 frame()->Push(&result); | |
| 578 } else { | 580 } else { |
| 579 // Anything else can be handled normally. | 581 // Anything else can be handled normally. |
| 580 Load(expr); | 582 Load(expr); |
| 581 } | 583 } |
| 582 } | 584 } |
| 583 | 585 |
| 584 | 586 |
| 585 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { | 587 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { |
| 586 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; | 588 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; |
| 587 ASSERT(scope()->arguments_shadow() != NULL); | 589 ASSERT(scope()->arguments_shadow() != NULL); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 616 Variable* arguments = scope()->arguments()->var(); | 618 Variable* arguments = scope()->arguments()->var(); |
| 617 Variable* shadow = scope()->arguments_shadow()->var(); | 619 Variable* shadow = scope()->arguments_shadow()->var(); |
| 618 ASSERT(arguments != NULL && arguments->slot() != NULL); | 620 ASSERT(arguments != NULL && arguments->slot() != NULL); |
| 619 ASSERT(shadow != NULL && shadow->slot() != NULL); | 621 ASSERT(shadow != NULL && shadow->slot() != NULL); |
| 620 JumpTarget done; | 622 JumpTarget done; |
| 621 bool skip_arguments = false; | 623 bool skip_arguments = false; |
| 622 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { | 624 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { |
| 623 // We have to skip storing into the arguments slot if it has already | 625 // We have to skip storing into the arguments slot if it has already |
| 624 // been written to. This can happen if the a function has a local | 626 // been written to. This can happen if the a function has a local |
| 625 // variable named 'arguments'. | 627 // variable named 'arguments'. |
| 626 LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF); | 628 Result probe = LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF); |
| 627 Result probe = frame_->Pop(); | |
| 628 if (probe.is_constant()) { | 629 if (probe.is_constant()) { |
| 629 // We have to skip updating the arguments object if it has | 630 // We have to skip updating the arguments object if it has |
| 630 // been assigned a proper value. | 631 // been assigned a proper value. |
| 631 skip_arguments = !probe.handle()->IsTheHole(); | 632 skip_arguments = !probe.handle()->IsTheHole(); |
| 632 } else { | 633 } else { |
| 633 __ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value())); | 634 __ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value())); |
| 634 probe.Unuse(); | 635 probe.Unuse(); |
| 635 done.Branch(not_equal); | 636 done.Branch(not_equal); |
| 636 } | 637 } |
| 637 } | 638 } |
| (...skipping 1692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2330 frame()->Dup(); | 2331 frame()->Dup(); |
| 2331 Handle<String> name = Factory::LookupAsciiSymbol("apply"); | 2332 Handle<String> name = Factory::LookupAsciiSymbol("apply"); |
| 2332 frame()->Push(name); | 2333 frame()->Push(name); |
| 2333 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); | 2334 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); |
| 2334 __ nop(); | 2335 __ nop(); |
| 2335 frame()->Push(&answer); | 2336 frame()->Push(&answer); |
| 2336 | 2337 |
| 2337 // Load the receiver and the existing arguments object onto the | 2338 // Load the receiver and the existing arguments object onto the |
| 2338 // expression stack. Avoid allocating the arguments object here. | 2339 // expression stack. Avoid allocating the arguments object here. |
| 2339 Load(receiver); | 2340 Load(receiver); |
| 2340 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); | 2341 Result existing_args = |
| 2342 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); | |
| 2343 frame()->Push(&existing_args); | |
| 2341 | 2344 |
| 2342 // Emit the source position information after having loaded the | 2345 // Emit the source position information after having loaded the |
| 2343 // receiver and the arguments. | 2346 // receiver and the arguments. |
| 2344 CodeForSourcePosition(position); | 2347 CodeForSourcePosition(position); |
| 2345 // Contents of frame at this point: | 2348 // Contents of frame at this point: |
| 2346 // Frame[0]: arguments object of the current function or the hole. | 2349 // Frame[0]: arguments object of the current function or the hole. |
| 2347 // Frame[1]: receiver | 2350 // Frame[1]: receiver |
| 2348 // Frame[2]: applicand.apply | 2351 // Frame[2]: applicand.apply |
| 2349 // Frame[3]: applicand. | 2352 // Frame[3]: applicand. |
| 2350 | 2353 |
| (...skipping 1632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3983 exit.Jump(); | 3986 exit.Jump(); |
| 3984 else_.Bind(); | 3987 else_.Bind(); |
| 3985 Load(node->else_expression()); | 3988 Load(node->else_expression()); |
| 3986 } | 3989 } |
| 3987 } | 3990 } |
| 3988 | 3991 |
| 3989 exit.Bind(); | 3992 exit.Bind(); |
| 3990 } | 3993 } |
| 3991 | 3994 |
| 3992 | 3995 |
| 3993 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { | 3996 Result CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { |
| 3997 Result result; | |
|
fschneider
2010/02/12 12:23:06
I'd move the declaration into the innermost necess
Kevin Millikin (Chromium)
2010/02/12 12:39:21
Ultimately it will be a field in the codegen state
| |
| 3994 if (slot->type() == Slot::LOOKUP) { | 3998 if (slot->type() == Slot::LOOKUP) { |
| 3995 ASSERT(slot->var()->is_dynamic()); | 3999 ASSERT(slot->var()->is_dynamic()); |
|
fschneider
2010/02/12 12:23:06
Declare result here instead.
| |
| 3996 | |
| 3997 JumpTarget slow; | 4000 JumpTarget slow; |
| 3998 JumpTarget done; | 4001 JumpTarget done; |
| 3999 Result value; | |
| 4000 | 4002 |
| 4001 // Generate fast-case code for variables that might be shadowed by | 4003 // Generate fast-case code for variables that might be shadowed by |
| 4002 // eval-introduced variables. Eval is used a lot without | 4004 // eval-introduced variables. Eval is used a lot without |
| 4003 // introducing variables. In those cases, we do not want to | 4005 // introducing variables. In those cases, we do not want to |
| 4004 // perform a runtime call for all variables in the scope | 4006 // perform a runtime call for all variables in the scope |
| 4005 // containing the eval. | 4007 // containing the eval. |
| 4006 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 4008 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
| 4007 value = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); | 4009 result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); |
| 4008 // If there was no control flow to slow, we can exit early. | 4010 // If there was no control flow to slow, we can exit early. |
| 4009 if (!slow.is_linked()) { | 4011 if (!slow.is_linked()) return result; |
| 4010 frame_->Push(&value); | 4012 done.Jump(&result); |
| 4011 return; | |
| 4012 } | |
| 4013 | |
| 4014 done.Jump(&value); | |
| 4015 | 4013 |
| 4016 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 4014 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
| 4017 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | 4015 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); |
|
fschneider
2010/02/12 12:23:06
Declare result here.
| |
| 4018 // Only generate the fast case for locals that rewrite to slots. | 4016 // Only generate the fast case for locals that rewrite to slots. |
| 4019 // This rules out argument loads. | 4017 // This rules out argument loads. |
| 4020 if (potential_slot != NULL) { | 4018 if (potential_slot != NULL) { |
| 4021 // Allocate a fresh register to use as a temp in | 4019 // Allocate a fresh register to use as a temp in |
| 4022 // ContextSlotOperandCheckExtensions and to hold the result | 4020 // ContextSlotOperandCheckExtensions and to hold the result |
| 4023 // value. | 4021 // value. |
| 4024 value = allocator_->Allocate(); | 4022 result = allocator()->Allocate(); |
| 4025 ASSERT(value.is_valid()); | 4023 ASSERT(result.is_valid()); |
| 4026 __ mov(value.reg(), | 4024 __ mov(result.reg(), |
| 4027 ContextSlotOperandCheckExtensions(potential_slot, | 4025 ContextSlotOperandCheckExtensions(potential_slot, |
| 4028 value, | 4026 result, |
| 4029 &slow)); | 4027 &slow)); |
| 4030 if (potential_slot->var()->mode() == Variable::CONST) { | 4028 if (potential_slot->var()->mode() == Variable::CONST) { |
| 4031 __ cmp(value.reg(), Factory::the_hole_value()); | 4029 __ cmp(result.reg(), Factory::the_hole_value()); |
| 4032 done.Branch(not_equal, &value); | 4030 done.Branch(not_equal, &result); |
| 4033 __ mov(value.reg(), Factory::undefined_value()); | 4031 __ mov(result.reg(), Factory::undefined_value()); |
| 4034 } | 4032 } |
| 4035 // There is always control flow to slow from | 4033 // There is always control flow to slow from |
| 4036 // ContextSlotOperandCheckExtensions so we have to jump around | 4034 // ContextSlotOperandCheckExtensions so we have to jump around |
| 4037 // it. | 4035 // it. |
| 4038 done.Jump(&value); | 4036 done.Jump(&result); |
| 4039 } | 4037 } |
| 4040 } | 4038 } |
| 4041 | 4039 |
| 4042 slow.Bind(); | 4040 slow.Bind(); |
| 4043 // A runtime call is inevitable. We eagerly sync frame elements | 4041 // A runtime call is inevitable. We eagerly sync frame elements |
| 4044 // to memory so that we can push the arguments directly into place | 4042 // to memory so that we can push the arguments directly into place |
| 4045 // on top of the frame. | 4043 // on top of the frame. |
| 4046 frame_->SyncRange(0, frame_->element_count() - 1); | 4044 frame()->SyncRange(0, frame()->element_count() - 1); |
| 4047 frame_->EmitPush(esi); | 4045 frame()->EmitPush(esi); |
| 4048 frame_->EmitPush(Immediate(slot->var()->name())); | 4046 frame()->EmitPush(Immediate(slot->var()->name())); |
| 4049 if (typeof_state == INSIDE_TYPEOF) { | 4047 if (typeof_state == INSIDE_TYPEOF) { |
| 4050 value = | 4048 result = |
| 4051 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 4049 frame()->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 4052 } else { | 4050 } else { |
| 4053 value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2); | 4051 result = frame()->CallRuntime(Runtime::kLoadContextSlot, 2); |
| 4054 } | 4052 } |
| 4055 | 4053 |
| 4056 done.Bind(&value); | 4054 done.Bind(&result); |
| 4057 frame_->Push(&value); | 4055 return result; |
| 4058 | 4056 |
| 4059 } else if (slot->var()->mode() == Variable::CONST) { | 4057 } else if (slot->var()->mode() == Variable::CONST) { |
| 4060 // Const slots may contain 'the hole' value (the constant hasn't been | 4058 // Const slots may contain 'the hole' value (the constant hasn't been |
| 4061 // initialized yet) which needs to be converted into the 'undefined' | 4059 // initialized yet) which needs to be converted into the 'undefined' |
| 4062 // value. | 4060 // value. |
| 4063 // | 4061 // |
| 4064 // We currently spill the virtual frame because constants use the | 4062 // We currently spill the virtual frame because constants use the |
| 4065 // potentially unsafe direct-frame access of SlotOperand. | 4063 // potentially unsafe direct-frame access of SlotOperand. |
| 4066 VirtualFrame::SpilledScope spilled_scope; | 4064 VirtualFrame::SpilledScope spilled_scope; |
| 4067 Comment cmnt(masm_, "[ Load const"); | 4065 Comment cmnt(masm_, "[ Load const"); |
| 4068 JumpTarget exit; | 4066 Label exit; |
| 4069 __ mov(ecx, SlotOperand(slot, ecx)); | 4067 __ mov(ecx, SlotOperand(slot, ecx)); |
| 4070 __ cmp(ecx, Factory::the_hole_value()); | 4068 __ cmp(ecx, Factory::the_hole_value()); |
| 4071 exit.Branch(not_equal); | 4069 __ j(not_equal, &exit); |
| 4072 __ mov(ecx, Factory::undefined_value()); | 4070 __ mov(ecx, Factory::undefined_value()); |
| 4073 exit.Bind(); | 4071 __ bind(&exit); |
| 4074 frame_->EmitPush(ecx); | 4072 return Result(ecx); |
| 4075 | 4073 |
| 4076 } else if (slot->type() == Slot::PARAMETER) { | 4074 } else if (slot->type() == Slot::PARAMETER) { |
| 4077 frame_->PushParameterAt(slot->index()); | 4075 frame()->PushParameterAt(slot->index()); |
| 4076 return frame()->Pop(); | |
|
fschneider
2010/02/12 12:23:06
Would it make sense to have a virtual frame functi
Kevin Millikin (Chromium)
2010/02/12 12:39:21
Yes, and PushParameterAt should go away. That's a
| |
| 4078 | 4077 |
| 4079 } else if (slot->type() == Slot::LOCAL) { | 4078 } else if (slot->type() == Slot::LOCAL) { |
| 4080 frame_->PushLocalAt(slot->index()); | 4079 frame()->PushLocalAt(slot->index()); |
| 4080 return frame()->Pop(); | |
| 4081 | 4081 |
| 4082 } else { | 4082 } else { |
| 4083 // The other remaining slot types (LOOKUP and GLOBAL) cannot reach | 4083 // The other remaining slot types (LOOKUP and GLOBAL) cannot reach |
|
fschneider
2010/02/12 12:23:06
Declare result here.
| |
| 4084 // here. | 4084 // here. |
| 4085 // | 4085 // |
| 4086 // The use of SlotOperand below is safe for an unspilled frame | 4086 // The use of SlotOperand below is safe for an unspilled frame |
| 4087 // because it will always be a context slot. | 4087 // because it will always be a context slot. |
| 4088 ASSERT(slot->type() == Slot::CONTEXT); | 4088 ASSERT(slot->type() == Slot::CONTEXT); |
| 4089 Result temp = allocator_->Allocate(); | 4089 result = allocator()->Allocate(); |
| 4090 ASSERT(temp.is_valid()); | 4090 ASSERT(result.is_valid()); |
| 4091 __ mov(temp.reg(), SlotOperand(slot, temp.reg())); | 4091 __ mov(result.reg(), SlotOperand(slot, result.reg())); |
| 4092 frame_->Push(&temp); | 4092 return result; |
| 4093 } | 4093 } |
| 4094 } | 4094 } |
| 4095 | 4095 |
| 4096 | 4096 |
| 4097 void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot, | 4097 Result CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot, |
| 4098 TypeofState state) { | 4098 TypeofState state) { |
| 4099 LoadFromSlot(slot, state); | 4099 Result result = LoadFromSlot(slot, state); |
| 4100 | 4100 |
| 4101 // Bail out quickly if we're not using lazy arguments allocation. | 4101 // Bail out quickly if we're not using lazy arguments allocation. |
| 4102 if (ArgumentsMode() != LAZY_ARGUMENTS_ALLOCATION) return; | 4102 if (ArgumentsMode() != LAZY_ARGUMENTS_ALLOCATION) return result; |
| 4103 | 4103 |
| 4104 // ... or if the slot isn't a non-parameter arguments slot. | 4104 // ... or if the slot isn't a non-parameter arguments slot. |
| 4105 if (slot->type() == Slot::PARAMETER || !slot->is_arguments()) return; | 4105 if (slot->type() == Slot::PARAMETER || !slot->is_arguments()) return result; |
| 4106 | |
| 4107 // Pop the loaded value from the stack. | |
| 4108 Result value = frame_->Pop(); | |
| 4109 | 4106 |
| 4110 // If the loaded value is a constant, we know if the arguments | 4107 // If the loaded value is a constant, we know if the arguments |
| 4111 // object has been lazily loaded yet. | 4108 // object has been lazily loaded yet. |
| 4112 if (value.is_constant()) { | 4109 if (result.is_constant()) { |
| 4113 if (value.handle()->IsTheHole()) { | 4110 if (result.handle()->IsTheHole()) { |
| 4114 Result arguments = StoreArgumentsObject(false); | 4111 result.Unuse(); |
| 4115 frame_->Push(&arguments); | 4112 return StoreArgumentsObject(false); |
| 4116 } else { | 4113 } else { |
| 4117 frame_->Push(&value); | 4114 return result; |
| 4118 } | 4115 } |
| 4119 return; | |
| 4120 } | 4116 } |
| 4121 | 4117 |
| 4122 // The loaded value is in a register. If it is the sentinel that | 4118 // The loaded value is in a register. If it is the sentinel that |
| 4123 // indicates that we haven't loaded the arguments object yet, we | 4119 // indicates that we haven't loaded the arguments object yet, we |
| 4124 // need to do it now. | 4120 // need to do it now. |
| 4125 JumpTarget exit; | 4121 JumpTarget exit; |
| 4126 __ cmp(Operand(value.reg()), Immediate(Factory::the_hole_value())); | 4122 __ cmp(Operand(result.reg()), Immediate(Factory::the_hole_value())); |
| 4127 frame_->Push(&value); | 4123 exit.Branch(not_equal, &result); |
| 4128 exit.Branch(not_equal); | 4124 |
| 4129 Result arguments = StoreArgumentsObject(false); | 4125 result.Unuse(); |
| 4130 frame_->SetElementAt(0, &arguments); | 4126 result = StoreArgumentsObject(false); |
| 4131 exit.Bind(); | 4127 exit.Bind(&result); |
| 4128 return result; | |
| 4132 } | 4129 } |
| 4133 | 4130 |
| 4134 | 4131 |
| 4135 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( | 4132 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( |
| 4136 Slot* slot, | 4133 Slot* slot, |
| 4137 TypeofState typeof_state, | 4134 TypeofState typeof_state, |
| 4138 JumpTarget* slow) { | 4135 JumpTarget* slow) { |
| 4139 // Check that no extension objects have been created by calls to | 4136 // Check that no extension objects have been created by calls to |
| 4140 // eval from the current scope to the global scope. | 4137 // eval from the current scope to the global scope. |
| 4141 Register context = esi; | 4138 Register context = esi; |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4295 // scope. | 4292 // scope. |
| 4296 } | 4293 } |
| 4297 | 4294 |
| 4298 exit.Bind(); | 4295 exit.Bind(); |
| 4299 } | 4296 } |
| 4300 } | 4297 } |
| 4301 | 4298 |
| 4302 | 4299 |
| 4303 void CodeGenerator::VisitSlot(Slot* node) { | 4300 void CodeGenerator::VisitSlot(Slot* node) { |
| 4304 Comment cmnt(masm_, "[ Slot"); | 4301 Comment cmnt(masm_, "[ Slot"); |
| 4305 LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF); | 4302 Result result = LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF); |
| 4303 frame()->Push(&result); | |
| 4306 } | 4304 } |
| 4307 | 4305 |
| 4308 | 4306 |
| 4309 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { | 4307 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { |
| 4310 Comment cmnt(masm_, "[ VariableProxy"); | 4308 Comment cmnt(masm_, "[ VariableProxy"); |
| 4311 Variable* var = node->var(); | 4309 Variable* var = node->var(); |
| 4312 Expression* expr = var->rewrite(); | 4310 Expression* expr = var->rewrite(); |
| 4313 if (expr != NULL) { | 4311 if (expr != NULL) { |
| 4314 Visit(expr); | 4312 Visit(expr); |
| 4315 } else { | 4313 } else { |
| (...skipping 2246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6562 Property* property = expression_->AsProperty(); | 6560 Property* property = expression_->AsProperty(); |
| 6563 if (property != NULL) { | 6561 if (property != NULL) { |
| 6564 cgen_->CodeForSourcePosition(property->position()); | 6562 cgen_->CodeForSourcePosition(property->position()); |
| 6565 } | 6563 } |
| 6566 | 6564 |
| 6567 switch (type_) { | 6565 switch (type_) { |
| 6568 case SLOT: { | 6566 case SLOT: { |
| 6569 Comment cmnt(masm, "[ Load from Slot"); | 6567 Comment cmnt(masm, "[ Load from Slot"); |
| 6570 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 6568 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); |
| 6571 ASSERT(slot != NULL); | 6569 ASSERT(slot != NULL); |
| 6572 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 6570 Result result = |
| 6573 if (!persist_after_get_) { | 6571 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
| 6574 cgen_->UnloadReference(this); | 6572 if (!persist_after_get_) set_unloaded(); |
| 6575 } | 6573 cgen_->frame()->Push(&result); |
| 6576 break; | 6574 break; |
| 6577 } | 6575 } |
| 6578 | 6576 |
| 6579 case NAMED: { | 6577 case NAMED: { |
| 6580 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 6578 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
| 6581 bool is_global = var != NULL; | 6579 bool is_global = var != NULL; |
| 6582 ASSERT(!is_global || var->is_global()); | 6580 ASSERT(!is_global || var->is_global()); |
| 6583 | 6581 |
| 6584 if (persist_after_get_) { | 6582 if (persist_after_get_) { |
| 6585 cgen_->frame()->Dup(); | 6583 cgen_->frame()->Dup(); |
| (...skipping 3530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10116 | 10114 |
| 10117 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 10115 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 10118 // tagged as a small integer. | 10116 // tagged as a small integer. |
| 10119 __ bind(&runtime); | 10117 __ bind(&runtime); |
| 10120 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); | 10118 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); |
| 10121 } | 10119 } |
| 10122 | 10120 |
| 10123 #undef __ | 10121 #undef __ |
| 10124 | 10122 |
| 10125 } } // namespace v8::internal | 10123 } } // namespace v8::internal |
| OLD | NEW |