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 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 // Note that iteration order is relevant here! If we have the same | 242 // Note that iteration order is relevant here! If we have the same |
243 // parameter twice (e.g., function (x, y, x)), and that parameter | 243 // parameter twice (e.g., function (x, y, x)), and that parameter |
244 // needs to be copied into the context, it must be the last argument | 244 // needs to be copied into the context, it must be the last argument |
245 // passed to the parameter that needs to be copied. This is a rare | 245 // passed to the parameter that needs to be copied. This is a rare |
246 // case so we don't check for it, instead we rely on the copying | 246 // case so we don't check for it, instead we rely on the copying |
247 // order: such a parameter is copied repeatedly into the same | 247 // order: such a parameter is copied repeatedly into the same |
248 // context location and thus the last value is what is seen inside | 248 // context location and thus the last value is what is seen inside |
249 // the function. | 249 // the function. |
250 for (int i = 0; i < scope()->num_parameters(); i++) { | 250 for (int i = 0; i < scope()->num_parameters(); i++) { |
251 Variable* par = scope()->parameter(i); | 251 Variable* par = scope()->parameter(i); |
252 Slot* slot = par->slot(); | 252 Slot* slot = par->AsSlot(); |
253 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 253 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
254 // The use of SlotOperand below is safe in unspilled code | 254 // The use of SlotOperand below is safe in unspilled code |
255 // because the slot is guaranteed to be a context slot. | 255 // because the slot is guaranteed to be a context slot. |
256 // | 256 // |
257 // There are no parameters in the global scope. | 257 // There are no parameters in the global scope. |
258 ASSERT(!scope()->is_global_scope()); | 258 ASSERT(!scope()->is_global_scope()); |
259 frame_->PushParameterAt(i); | 259 frame_->PushParameterAt(i); |
260 Result value = frame_->Pop(); | 260 Result value = frame_->Pop(); |
261 value.ToRegister(); | 261 value.ToRegister(); |
262 | 262 |
(...skipping 15 matching lines...) Expand all Loading... |
278 // Store the arguments object. This must happen after context | 278 // Store the arguments object. This must happen after context |
279 // initialization because the arguments object may be stored in | 279 // initialization because the arguments object may be stored in |
280 // the context. | 280 // the context. |
281 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { | 281 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { |
282 StoreArgumentsObject(true); | 282 StoreArgumentsObject(true); |
283 } | 283 } |
284 | 284 |
285 // Initialize ThisFunction reference if present. | 285 // Initialize ThisFunction reference if present. |
286 if (scope()->is_function_scope() && scope()->function() != NULL) { | 286 if (scope()->is_function_scope() && scope()->function() != NULL) { |
287 frame_->Push(Factory::the_hole_value()); | 287 frame_->Push(Factory::the_hole_value()); |
288 StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT); | 288 StoreToSlot(scope()->function()->AsSlot(), NOT_CONST_INIT); |
289 } | 289 } |
290 | 290 |
291 | 291 |
292 // Initialize the function return target after the locals are set | 292 // Initialize the function return target after the locals are set |
293 // up, because it needs the expected frame height from the frame. | 293 // up, because it needs the expected frame height from the frame. |
294 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); | 294 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); |
295 function_return_is_shadowed_ = false; | 295 function_return_is_shadowed_ = false; |
296 | 296 |
297 // Generate code to 'execute' declarations and initialize functions | 297 // Generate code to 'execute' declarations and initialize functions |
298 // (source elements). In case of an illegal redeclaration we need to | 298 // (source elements). In case of an illegal redeclaration we need to |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
710 Variable* variable = expr->AsVariableProxy()->AsVariable(); | 710 Variable* variable = expr->AsVariableProxy()->AsVariable(); |
711 if (variable != NULL && !variable->is_this() && variable->is_global()) { | 711 if (variable != NULL && !variable->is_this() && variable->is_global()) { |
712 // For a global variable we build the property reference | 712 // For a global variable we build the property reference |
713 // <global>.<variable> and perform a (regular non-contextual) property | 713 // <global>.<variable> and perform a (regular non-contextual) property |
714 // load to make sure we do not get reference errors. | 714 // load to make sure we do not get reference errors. |
715 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 715 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); |
716 Literal key(variable->name()); | 716 Literal key(variable->name()); |
717 Property property(&global, &key, RelocInfo::kNoPosition); | 717 Property property(&global, &key, RelocInfo::kNoPosition); |
718 Reference ref(this, &property); | 718 Reference ref(this, &property); |
719 ref.GetValue(); | 719 ref.GetValue(); |
720 } else if (variable != NULL && variable->slot() != NULL) { | 720 } else if (variable != NULL && variable->AsSlot() != NULL) { |
721 // For a variable that rewrites to a slot, we signal it is the immediate | 721 // For a variable that rewrites to a slot, we signal it is the immediate |
722 // subexpression of a typeof. | 722 // subexpression of a typeof. |
723 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); | 723 LoadFromSlotCheckForArguments(variable->AsSlot(), INSIDE_TYPEOF); |
724 } else { | 724 } else { |
725 // Anything else can be handled normally. | 725 // Anything else can be handled normally. |
726 Load(expr); | 726 Load(expr); |
727 } | 727 } |
728 } | 728 } |
729 | 729 |
730 | 730 |
731 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { | 731 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { |
732 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; | 732 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; |
733 ASSERT(scope()->arguments_shadow() != NULL); | 733 ASSERT(scope()->arguments_shadow() != NULL); |
(...skipping 18 matching lines...) Expand all Loading... |
752 frame_->Push(Factory::the_hole_value()); | 752 frame_->Push(Factory::the_hole_value()); |
753 } else { | 753 } else { |
754 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | 754 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
755 frame_->PushFunction(); | 755 frame_->PushFunction(); |
756 frame_->PushReceiverSlotAddress(); | 756 frame_->PushReceiverSlotAddress(); |
757 frame_->Push(Smi::FromInt(scope()->num_parameters())); | 757 frame_->Push(Smi::FromInt(scope()->num_parameters())); |
758 Result result = frame_->CallStub(&stub, 3); | 758 Result result = frame_->CallStub(&stub, 3); |
759 frame_->Push(&result); | 759 frame_->Push(&result); |
760 } | 760 } |
761 | 761 |
762 Variable* arguments = scope()->arguments()->var(); | 762 Variable* arguments = scope()->arguments(); |
763 Variable* shadow = scope()->arguments_shadow()->var(); | 763 Variable* shadow = scope()->arguments_shadow(); |
764 ASSERT(arguments != NULL && arguments->slot() != NULL); | 764 ASSERT(arguments != NULL && arguments->AsSlot() != NULL); |
765 ASSERT(shadow != NULL && shadow->slot() != NULL); | 765 ASSERT(shadow != NULL && shadow->AsSlot() != NULL); |
766 JumpTarget done; | 766 JumpTarget done; |
767 bool skip_arguments = false; | 767 bool skip_arguments = false; |
768 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { | 768 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { |
769 // We have to skip storing into the arguments slot if it has | 769 // We have to skip storing into the arguments slot if it has |
770 // already been written to. This can happen if the a function | 770 // already been written to. This can happen if the a function |
771 // has a local variable named 'arguments'. | 771 // has a local variable named 'arguments'. |
772 LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF); | 772 LoadFromSlot(arguments->AsSlot(), NOT_INSIDE_TYPEOF); |
773 Result probe = frame_->Pop(); | 773 Result probe = frame_->Pop(); |
774 if (probe.is_constant()) { | 774 if (probe.is_constant()) { |
775 // We have to skip updating the arguments object if it has | 775 // We have to skip updating the arguments object if it has |
776 // been assigned a proper value. | 776 // been assigned a proper value. |
777 skip_arguments = !probe.handle()->IsTheHole(); | 777 skip_arguments = !probe.handle()->IsTheHole(); |
778 } else { | 778 } else { |
779 __ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value())); | 779 __ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value())); |
780 probe.Unuse(); | 780 probe.Unuse(); |
781 done.Branch(not_equal); | 781 done.Branch(not_equal); |
782 } | 782 } |
783 } | 783 } |
784 if (!skip_arguments) { | 784 if (!skip_arguments) { |
785 StoreToSlot(arguments->slot(), NOT_CONST_INIT); | 785 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT); |
786 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); | 786 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); |
787 } | 787 } |
788 StoreToSlot(shadow->slot(), NOT_CONST_INIT); | 788 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT); |
789 return frame_->Pop(); | 789 return frame_->Pop(); |
790 } | 790 } |
791 | 791 |
792 //------------------------------------------------------------------------------ | 792 //------------------------------------------------------------------------------ |
793 // CodeGenerator implementation of variables, lookups, and stores. | 793 // CodeGenerator implementation of variables, lookups, and stores. |
794 | 794 |
795 Reference::Reference(CodeGenerator* cgen, | 795 Reference::Reference(CodeGenerator* cgen, |
796 Expression* expression, | 796 Expression* expression, |
797 bool persist_after_get) | 797 bool persist_after_get) |
798 : cgen_(cgen), | 798 : cgen_(cgen), |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 // property. Global variables are treated as named property references. | 835 // property. Global variables are treated as named property references. |
836 if (var->is_global()) { | 836 if (var->is_global()) { |
837 // If eax is free, the register allocator prefers it. Thus the code | 837 // If eax is free, the register allocator prefers it. Thus the code |
838 // generator will load the global object into eax, which is where | 838 // generator will load the global object into eax, which is where |
839 // LoadIC wants it. Most uses of Reference call LoadIC directly | 839 // LoadIC wants it. Most uses of Reference call LoadIC directly |
840 // after the reference is created. | 840 // after the reference is created. |
841 frame_->Spill(eax); | 841 frame_->Spill(eax); |
842 LoadGlobal(); | 842 LoadGlobal(); |
843 ref->set_type(Reference::NAMED); | 843 ref->set_type(Reference::NAMED); |
844 } else { | 844 } else { |
845 ASSERT(var->slot() != NULL); | 845 ASSERT(var->AsSlot() != NULL); |
846 ref->set_type(Reference::SLOT); | 846 ref->set_type(Reference::SLOT); |
847 } | 847 } |
848 } else { | 848 } else { |
849 // Anything else is a runtime error. | 849 // Anything else is a runtime error. |
850 Load(e); | 850 Load(e); |
851 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); | 851 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); |
852 } | 852 } |
853 | 853 |
854 in_spilled_code_ = was_in_spilled_code; | 854 in_spilled_code_ = was_in_spilled_code; |
855 } | 855 } |
(...skipping 2411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3267 frame()->Dup(); | 3267 frame()->Dup(); |
3268 Handle<String> name = Factory::LookupAsciiSymbol("apply"); | 3268 Handle<String> name = Factory::LookupAsciiSymbol("apply"); |
3269 frame()->Push(name); | 3269 frame()->Push(name); |
3270 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); | 3270 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); |
3271 __ nop(); | 3271 __ nop(); |
3272 frame()->Push(&answer); | 3272 frame()->Push(&answer); |
3273 | 3273 |
3274 // Load the receiver and the existing arguments object onto the | 3274 // Load the receiver and the existing arguments object onto the |
3275 // expression stack. Avoid allocating the arguments object here. | 3275 // expression stack. Avoid allocating the arguments object here. |
3276 Load(receiver); | 3276 Load(receiver); |
3277 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); | 3277 LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF); |
3278 | 3278 |
3279 // Emit the source position information after having loaded the | 3279 // Emit the source position information after having loaded the |
3280 // receiver and the arguments. | 3280 // receiver and the arguments. |
3281 CodeForSourcePosition(position); | 3281 CodeForSourcePosition(position); |
3282 // Contents of frame at this point: | 3282 // Contents of frame at this point: |
3283 // Frame[0]: arguments object of the current function or the hole. | 3283 // Frame[0]: arguments object of the current function or the hole. |
3284 // Frame[1]: receiver | 3284 // Frame[1]: receiver |
3285 // Frame[2]: applicand.apply | 3285 // Frame[2]: applicand.apply |
3286 // Frame[3]: applicand. | 3286 // Frame[3]: applicand. |
3287 | 3287 |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3529 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); | 3529 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); |
3530 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | 3530 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); |
3531 // Return value is ignored. | 3531 // Return value is ignored. |
3532 } | 3532 } |
3533 | 3533 |
3534 | 3534 |
3535 void CodeGenerator::VisitDeclaration(Declaration* node) { | 3535 void CodeGenerator::VisitDeclaration(Declaration* node) { |
3536 Comment cmnt(masm_, "[ Declaration"); | 3536 Comment cmnt(masm_, "[ Declaration"); |
3537 Variable* var = node->proxy()->var(); | 3537 Variable* var = node->proxy()->var(); |
3538 ASSERT(var != NULL); // must have been resolved | 3538 ASSERT(var != NULL); // must have been resolved |
3539 Slot* slot = var->slot(); | 3539 Slot* slot = var->AsSlot(); |
3540 | 3540 |
3541 // If it was not possible to allocate the variable at compile time, | 3541 // If it was not possible to allocate the variable at compile time, |
3542 // we need to "declare" it at runtime to make sure it actually | 3542 // we need to "declare" it at runtime to make sure it actually |
3543 // exists in the local context. | 3543 // exists in the local context. |
3544 if (slot != NULL && slot->type() == Slot::LOOKUP) { | 3544 if (slot != NULL && slot->type() == Slot::LOOKUP) { |
3545 // Variables with a "LOOKUP" slot were introduced as non-locals | 3545 // Variables with a "LOOKUP" slot were introduced as non-locals |
3546 // during variable resolution and must have mode DYNAMIC. | 3546 // during variable resolution and must have mode DYNAMIC. |
3547 ASSERT(var->is_dynamic()); | 3547 ASSERT(var->is_dynamic()); |
3548 // For now, just do a runtime call. Sync the virtual frame eagerly | 3548 // For now, just do a runtime call. Sync the virtual frame eagerly |
3549 // so we can simply push the arguments into place. | 3549 // so we can simply push the arguments into place. |
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4245 | 4245 |
4246 CheckStack(); // TODO(1222600): ignore if body contains calls. | 4246 CheckStack(); // TODO(1222600): ignore if body contains calls. |
4247 | 4247 |
4248 // We know that the loop index is a smi if it is not modified in the | 4248 // We know that the loop index is a smi if it is not modified in the |
4249 // loop body and it is checked against a constant limit in the loop | 4249 // loop body and it is checked against a constant limit in the loop |
4250 // condition. In this case, we reset the static type information of the | 4250 // condition. In this case, we reset the static type information of the |
4251 // loop index to smi before compiling the body, the update expression, and | 4251 // loop index to smi before compiling the body, the update expression, and |
4252 // the bottom check of the loop condition. | 4252 // the bottom check of the loop condition. |
4253 if (node->is_fast_smi_loop()) { | 4253 if (node->is_fast_smi_loop()) { |
4254 // Set number type of the loop variable to smi. | 4254 // Set number type of the loop variable to smi. |
4255 SetTypeForStackSlot(node->loop_variable()->slot(), TypeInfo::Smi()); | 4255 SetTypeForStackSlot(node->loop_variable()->AsSlot(), TypeInfo::Smi()); |
4256 } | 4256 } |
4257 | 4257 |
4258 Visit(node->body()); | 4258 Visit(node->body()); |
4259 | 4259 |
4260 // If there is an update expression, compile it if necessary. | 4260 // If there is an update expression, compile it if necessary. |
4261 if (node->next() != NULL) { | 4261 if (node->next() != NULL) { |
4262 if (node->continue_target()->is_linked()) { | 4262 if (node->continue_target()->is_linked()) { |
4263 node->continue_target()->Bind(); | 4263 node->continue_target()->Bind(); |
4264 } | 4264 } |
4265 | 4265 |
4266 // Control can reach the update by falling out of the body or by a | 4266 // Control can reach the update by falling out of the body or by a |
4267 // continue. | 4267 // continue. |
4268 if (has_valid_frame()) { | 4268 if (has_valid_frame()) { |
4269 // Record the source position of the statement as this code which | 4269 // Record the source position of the statement as this code which |
4270 // is after the code for the body actually belongs to the loop | 4270 // is after the code for the body actually belongs to the loop |
4271 // statement and not the body. | 4271 // statement and not the body. |
4272 CodeForStatementPosition(node); | 4272 CodeForStatementPosition(node); |
4273 Visit(node->next()); | 4273 Visit(node->next()); |
4274 } | 4274 } |
4275 } | 4275 } |
4276 | 4276 |
4277 // Set the type of the loop variable to smi before compiling the test | 4277 // Set the type of the loop variable to smi before compiling the test |
4278 // expression if we are in a fast smi loop condition. | 4278 // expression if we are in a fast smi loop condition. |
4279 if (node->is_fast_smi_loop() && has_valid_frame()) { | 4279 if (node->is_fast_smi_loop() && has_valid_frame()) { |
4280 // Set number type of the loop variable to smi. | 4280 // Set number type of the loop variable to smi. |
4281 SetTypeForStackSlot(node->loop_variable()->slot(), TypeInfo::Smi()); | 4281 SetTypeForStackSlot(node->loop_variable()->AsSlot(), TypeInfo::Smi()); |
4282 } | 4282 } |
4283 | 4283 |
4284 // Based on the condition analysis, compile the backward jump as | 4284 // Based on the condition analysis, compile the backward jump as |
4285 // necessary. | 4285 // necessary. |
4286 switch (info) { | 4286 switch (info) { |
4287 case ALWAYS_TRUE: | 4287 case ALWAYS_TRUE: |
4288 if (has_valid_frame()) { | 4288 if (has_valid_frame()) { |
4289 if (node->next() == NULL) { | 4289 if (node->next() == NULL) { |
4290 node->continue_target()->Jump(); | 4290 node->continue_target()->Jump(); |
4291 } else { | 4291 } else { |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4570 | 4570 |
4571 JumpTarget try_block; | 4571 JumpTarget try_block; |
4572 JumpTarget exit; | 4572 JumpTarget exit; |
4573 | 4573 |
4574 try_block.Call(); | 4574 try_block.Call(); |
4575 // --- Catch block --- | 4575 // --- Catch block --- |
4576 frame_->EmitPush(eax); | 4576 frame_->EmitPush(eax); |
4577 | 4577 |
4578 // Store the caught exception in the catch variable. | 4578 // Store the caught exception in the catch variable. |
4579 Variable* catch_var = node->catch_var()->var(); | 4579 Variable* catch_var = node->catch_var()->var(); |
4580 ASSERT(catch_var != NULL && catch_var->slot() != NULL); | 4580 ASSERT(catch_var != NULL && catch_var->AsSlot() != NULL); |
4581 StoreToSlot(catch_var->slot(), NOT_CONST_INIT); | 4581 StoreToSlot(catch_var->AsSlot(), NOT_CONST_INIT); |
4582 | 4582 |
4583 // Remove the exception from the stack. | 4583 // Remove the exception from the stack. |
4584 frame_->Drop(); | 4584 frame_->Drop(); |
4585 | 4585 |
4586 VisitStatementsAndSpill(node->catch_block()->statements()); | 4586 VisitStatementsAndSpill(node->catch_block()->statements()); |
4587 if (has_valid_frame()) { | 4587 if (has_valid_frame()) { |
4588 exit.Jump(); | 4588 exit.Jump(); |
4589 } | 4589 } |
4590 | 4590 |
4591 | 4591 |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5166 // Generate fast-case code for variables that might be shadowed by | 5166 // Generate fast-case code for variables that might be shadowed by |
5167 // eval-introduced variables. Eval is used a lot without | 5167 // eval-introduced variables. Eval is used a lot without |
5168 // introducing variables. In those cases, we do not want to | 5168 // introducing variables. In those cases, we do not want to |
5169 // perform a runtime call for all variables in the scope | 5169 // perform a runtime call for all variables in the scope |
5170 // containing the eval. | 5170 // containing the eval. |
5171 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 5171 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
5172 *result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow); | 5172 *result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow); |
5173 done->Jump(result); | 5173 done->Jump(result); |
5174 | 5174 |
5175 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 5175 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
5176 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | 5176 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); |
5177 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | 5177 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); |
5178 if (potential_slot != NULL) { | 5178 if (potential_slot != NULL) { |
5179 // Generate fast case for locals that rewrite to slots. | 5179 // Generate fast case for locals that rewrite to slots. |
5180 // Allocate a fresh register to use as a temp in | 5180 // Allocate a fresh register to use as a temp in |
5181 // ContextSlotOperandCheckExtensions and to hold the result | 5181 // ContextSlotOperandCheckExtensions and to hold the result |
5182 // value. | 5182 // value. |
5183 *result = allocator()->Allocate(); | 5183 *result = allocator()->Allocate(); |
5184 ASSERT(result->is_valid()); | 5184 ASSERT(result->is_valid()); |
5185 __ mov(result->reg(), | 5185 __ mov(result->reg(), |
5186 ContextSlotOperandCheckExtensions(potential_slot, *result, slow)); | 5186 ContextSlotOperandCheckExtensions(potential_slot, *result, slow)); |
(...skipping 12 matching lines...) Expand all Loading... |
5199 if (obj_proxy != NULL && | 5199 if (obj_proxy != NULL && |
5200 key_literal != NULL && | 5200 key_literal != NULL && |
5201 obj_proxy->IsArguments() && | 5201 obj_proxy->IsArguments() && |
5202 key_literal->handle()->IsSmi()) { | 5202 key_literal->handle()->IsSmi()) { |
5203 // Load arguments object if there are no eval-introduced | 5203 // Load arguments object if there are no eval-introduced |
5204 // variables. Then load the argument from the arguments | 5204 // variables. Then load the argument from the arguments |
5205 // object using keyed load. | 5205 // object using keyed load. |
5206 Result arguments = allocator()->Allocate(); | 5206 Result arguments = allocator()->Allocate(); |
5207 ASSERT(arguments.is_valid()); | 5207 ASSERT(arguments.is_valid()); |
5208 __ mov(arguments.reg(), | 5208 __ mov(arguments.reg(), |
5209 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | 5209 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
5210 arguments, | 5210 arguments, |
5211 slow)); | 5211 slow)); |
5212 frame_->Push(&arguments); | 5212 frame_->Push(&arguments); |
5213 frame_->Push(key_literal->handle()); | 5213 frame_->Push(key_literal->handle()); |
5214 *result = EmitKeyedLoad(); | 5214 *result = EmitKeyedLoad(); |
5215 done->Jump(result); | 5215 done->Jump(result); |
5216 } | 5216 } |
5217 } | 5217 } |
5218 } | 5218 } |
5219 } | 5219 } |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5707 } | 5707 } |
5708 | 5708 |
5709 | 5709 |
5710 void CodeGenerator::EmitSlotAssignment(Assignment* node) { | 5710 void CodeGenerator::EmitSlotAssignment(Assignment* node) { |
5711 #ifdef DEBUG | 5711 #ifdef DEBUG |
5712 int original_height = frame()->height(); | 5712 int original_height = frame()->height(); |
5713 #endif | 5713 #endif |
5714 Comment cmnt(masm(), "[ Variable Assignment"); | 5714 Comment cmnt(masm(), "[ Variable Assignment"); |
5715 Variable* var = node->target()->AsVariableProxy()->AsVariable(); | 5715 Variable* var = node->target()->AsVariableProxy()->AsVariable(); |
5716 ASSERT(var != NULL); | 5716 ASSERT(var != NULL); |
5717 Slot* slot = var->slot(); | 5717 Slot* slot = var->AsSlot(); |
5718 ASSERT(slot != NULL); | 5718 ASSERT(slot != NULL); |
5719 | 5719 |
5720 // Evaluate the right-hand side. | 5720 // Evaluate the right-hand side. |
5721 if (node->is_compound()) { | 5721 if (node->is_compound()) { |
5722 // For a compound assignment the right-hand side is a binary operation | 5722 // For a compound assignment the right-hand side is a binary operation |
5723 // between the current property value and the actual right-hand side. | 5723 // between the current property value and the actual right-hand side. |
5724 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 5724 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
5725 Load(node->value()); | 5725 Load(node->value()); |
5726 | 5726 |
5727 // Perform the binary operation. | 5727 // Perform the binary operation. |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6056 | 6056 |
6057 // Result to hold the result of the function resolution and the | 6057 // Result to hold the result of the function resolution and the |
6058 // final result of the eval call. | 6058 // final result of the eval call. |
6059 Result result; | 6059 Result result; |
6060 | 6060 |
6061 // If we know that eval can only be shadowed by eval-introduced | 6061 // If we know that eval can only be shadowed by eval-introduced |
6062 // variables we attempt to load the global eval function directly | 6062 // variables we attempt to load the global eval function directly |
6063 // in generated code. If we succeed, there is no need to perform a | 6063 // in generated code. If we succeed, there is no need to perform a |
6064 // context lookup in the runtime system. | 6064 // context lookup in the runtime system. |
6065 JumpTarget done; | 6065 JumpTarget done; |
6066 if (var->slot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { | 6066 if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { |
6067 ASSERT(var->slot()->type() == Slot::LOOKUP); | 6067 ASSERT(var->AsSlot()->type() == Slot::LOOKUP); |
6068 JumpTarget slow; | 6068 JumpTarget slow; |
6069 // Prepare the stack for the call to | 6069 // Prepare the stack for the call to |
6070 // ResolvePossiblyDirectEvalNoLookup by pushing the loaded | 6070 // ResolvePossiblyDirectEvalNoLookup by pushing the loaded |
6071 // function, the first argument to the eval call and the | 6071 // function, the first argument to the eval call and the |
6072 // receiver. | 6072 // receiver. |
6073 Result fun = LoadFromGlobalSlotCheckExtensions(var->slot(), | 6073 Result fun = LoadFromGlobalSlotCheckExtensions(var->AsSlot(), |
6074 NOT_INSIDE_TYPEOF, | 6074 NOT_INSIDE_TYPEOF, |
6075 &slow); | 6075 &slow); |
6076 frame_->Push(&fun); | 6076 frame_->Push(&fun); |
6077 if (arg_count > 0) { | 6077 if (arg_count > 0) { |
6078 frame_->PushElementAt(arg_count); | 6078 frame_->PushElementAt(arg_count); |
6079 } else { | 6079 } else { |
6080 frame_->Push(Factory::undefined_value()); | 6080 frame_->Push(Factory::undefined_value()); |
6081 } | 6081 } |
6082 frame_->PushParameterAt(-1); | 6082 frame_->PushParameterAt(-1); |
6083 | 6083 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6146 frame_->Push(var->name()); | 6146 frame_->Push(var->name()); |
6147 | 6147 |
6148 // Call the IC initialization code. | 6148 // Call the IC initialization code. |
6149 CodeForSourcePosition(node->position()); | 6149 CodeForSourcePosition(node->position()); |
6150 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, | 6150 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, |
6151 arg_count, | 6151 arg_count, |
6152 loop_nesting()); | 6152 loop_nesting()); |
6153 frame_->RestoreContextRegister(); | 6153 frame_->RestoreContextRegister(); |
6154 frame_->Push(&result); | 6154 frame_->Push(&result); |
6155 | 6155 |
6156 } else if (var != NULL && var->slot() != NULL && | 6156 } else if (var != NULL && var->AsSlot() != NULL && |
6157 var->slot()->type() == Slot::LOOKUP) { | 6157 var->AsSlot()->type() == Slot::LOOKUP) { |
6158 // ---------------------------------- | 6158 // ---------------------------------- |
6159 // JavaScript examples: | 6159 // JavaScript examples: |
6160 // | 6160 // |
6161 // with (obj) foo(1, 2, 3) // foo may be in obj. | 6161 // with (obj) foo(1, 2, 3) // foo may be in obj. |
6162 // | 6162 // |
6163 // function f() {}; | 6163 // function f() {}; |
6164 // function g() { | 6164 // function g() { |
6165 // eval(...); | 6165 // eval(...); |
6166 // f(); // f could be in extension object. | 6166 // f(); // f could be in extension object. |
6167 // } | 6167 // } |
6168 // ---------------------------------- | 6168 // ---------------------------------- |
6169 | 6169 |
6170 JumpTarget slow, done; | 6170 JumpTarget slow, done; |
6171 Result function; | 6171 Result function; |
6172 | 6172 |
6173 // Generate fast case for loading functions from slots that | 6173 // Generate fast case for loading functions from slots that |
6174 // correspond to local/global variables or arguments unless they | 6174 // correspond to local/global variables or arguments unless they |
6175 // are shadowed by eval-introduced bindings. | 6175 // are shadowed by eval-introduced bindings. |
6176 EmitDynamicLoadFromSlotFastCase(var->slot(), | 6176 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
6177 NOT_INSIDE_TYPEOF, | 6177 NOT_INSIDE_TYPEOF, |
6178 &function, | 6178 &function, |
6179 &slow, | 6179 &slow, |
6180 &done); | 6180 &done); |
6181 | 6181 |
6182 slow.Bind(); | 6182 slow.Bind(); |
6183 // Enter the runtime system to load the function from the context. | 6183 // Enter the runtime system to load the function from the context. |
6184 // Sync the frame so we can push the arguments directly into | 6184 // Sync the frame so we can push the arguments directly into |
6185 // place. | 6185 // place. |
6186 frame_->SyncRange(0, frame_->element_count() - 1); | 6186 frame_->SyncRange(0, frame_->element_count() - 1); |
(...skipping 1859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8046 if (property != NULL) { | 8046 if (property != NULL) { |
8047 Load(property->obj()); | 8047 Load(property->obj()); |
8048 Load(property->key()); | 8048 Load(property->key()); |
8049 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); | 8049 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); |
8050 frame_->Push(&answer); | 8050 frame_->Push(&answer); |
8051 return; | 8051 return; |
8052 } | 8052 } |
8053 | 8053 |
8054 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 8054 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
8055 if (variable != NULL) { | 8055 if (variable != NULL) { |
8056 Slot* slot = variable->slot(); | 8056 Slot* slot = variable->AsSlot(); |
8057 if (variable->is_global()) { | 8057 if (variable->is_global()) { |
8058 LoadGlobal(); | 8058 LoadGlobal(); |
8059 frame_->Push(variable->name()); | 8059 frame_->Push(variable->name()); |
8060 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, | 8060 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, |
8061 CALL_FUNCTION, 2); | 8061 CALL_FUNCTION, 2); |
8062 frame_->Push(&answer); | 8062 frame_->Push(&answer); |
8063 return; | 8063 return; |
8064 | 8064 |
8065 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 8065 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
8066 // Call the runtime to look up the context holding the named | 8066 // Call the runtime to look up the context holding the named |
(...skipping 1713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9780 | 9780 |
9781 // Record the source position for the property load. | 9781 // Record the source position for the property load. |
9782 Property* property = expression_->AsProperty(); | 9782 Property* property = expression_->AsProperty(); |
9783 if (property != NULL) { | 9783 if (property != NULL) { |
9784 cgen_->CodeForSourcePosition(property->position()); | 9784 cgen_->CodeForSourcePosition(property->position()); |
9785 } | 9785 } |
9786 | 9786 |
9787 switch (type_) { | 9787 switch (type_) { |
9788 case SLOT: { | 9788 case SLOT: { |
9789 Comment cmnt(masm, "[ Load from Slot"); | 9789 Comment cmnt(masm, "[ Load from Slot"); |
9790 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 9790 Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot(); |
9791 ASSERT(slot != NULL); | 9791 ASSERT(slot != NULL); |
9792 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 9792 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
9793 if (!persist_after_get_) set_unloaded(); | 9793 if (!persist_after_get_) set_unloaded(); |
9794 break; | 9794 break; |
9795 } | 9795 } |
9796 | 9796 |
9797 case NAMED: { | 9797 case NAMED: { |
9798 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 9798 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
9799 bool is_global = var != NULL; | 9799 bool is_global = var != NULL; |
9800 ASSERT(!is_global || var->is_global()); | 9800 ASSERT(!is_global || var->is_global()); |
(...skipping 24 matching lines...) Expand all Loading... |
9825 void Reference::TakeValue() { | 9825 void Reference::TakeValue() { |
9826 // For non-constant frame-allocated slots, we invalidate the value in the | 9826 // For non-constant frame-allocated slots, we invalidate the value in the |
9827 // slot. For all others, we fall back on GetValue. | 9827 // slot. For all others, we fall back on GetValue. |
9828 ASSERT(!cgen_->in_spilled_code()); | 9828 ASSERT(!cgen_->in_spilled_code()); |
9829 ASSERT(!is_illegal()); | 9829 ASSERT(!is_illegal()); |
9830 if (type_ != SLOT) { | 9830 if (type_ != SLOT) { |
9831 GetValue(); | 9831 GetValue(); |
9832 return; | 9832 return; |
9833 } | 9833 } |
9834 | 9834 |
9835 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 9835 Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot(); |
9836 ASSERT(slot != NULL); | 9836 ASSERT(slot != NULL); |
9837 if (slot->type() == Slot::LOOKUP || | 9837 if (slot->type() == Slot::LOOKUP || |
9838 slot->type() == Slot::CONTEXT || | 9838 slot->type() == Slot::CONTEXT || |
9839 slot->var()->mode() == Variable::CONST || | 9839 slot->var()->mode() == Variable::CONST || |
9840 slot->is_arguments()) { | 9840 slot->is_arguments()) { |
9841 GetValue(); | 9841 GetValue(); |
9842 return; | 9842 return; |
9843 } | 9843 } |
9844 | 9844 |
9845 // Only non-constant, frame-allocated parameters and locals can | 9845 // Only non-constant, frame-allocated parameters and locals can |
(...skipping 12 matching lines...) Expand all Loading... |
9858 } | 9858 } |
9859 | 9859 |
9860 | 9860 |
9861 void Reference::SetValue(InitState init_state) { | 9861 void Reference::SetValue(InitState init_state) { |
9862 ASSERT(cgen_->HasValidEntryRegisters()); | 9862 ASSERT(cgen_->HasValidEntryRegisters()); |
9863 ASSERT(!is_illegal()); | 9863 ASSERT(!is_illegal()); |
9864 MacroAssembler* masm = cgen_->masm(); | 9864 MacroAssembler* masm = cgen_->masm(); |
9865 switch (type_) { | 9865 switch (type_) { |
9866 case SLOT: { | 9866 case SLOT: { |
9867 Comment cmnt(masm, "[ Store to Slot"); | 9867 Comment cmnt(masm, "[ Store to Slot"); |
9868 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 9868 Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot(); |
9869 ASSERT(slot != NULL); | 9869 ASSERT(slot != NULL); |
9870 cgen_->StoreToSlot(slot, init_state); | 9870 cgen_->StoreToSlot(slot, init_state); |
9871 set_unloaded(); | 9871 set_unloaded(); |
9872 break; | 9872 break; |
9873 } | 9873 } |
9874 | 9874 |
9875 case NAMED: { | 9875 case NAMED: { |
9876 Comment cmnt(masm, "[ Store to named Property"); | 9876 Comment cmnt(masm, "[ Store to named Property"); |
9877 Result answer = cgen_->EmitNamedStore(GetName(), false); | 9877 Result answer = cgen_->EmitNamedStore(GetName(), false); |
9878 cgen_->frame()->Push(&answer); | 9878 cgen_->frame()->Push(&answer); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10101 masm.GetCode(&desc); | 10101 masm.GetCode(&desc); |
10102 // Call the function from C++. | 10102 // Call the function from C++. |
10103 return FUNCTION_CAST<MemCopyFunction>(buffer); | 10103 return FUNCTION_CAST<MemCopyFunction>(buffer); |
10104 } | 10104 } |
10105 | 10105 |
10106 #undef __ | 10106 #undef __ |
10107 | 10107 |
10108 } } // namespace v8::internal | 10108 } } // namespace v8::internal |
10109 | 10109 |
10110 #endif // V8_TARGET_ARCH_IA32 | 10110 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |