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

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

Issue 3432022: Clean up some messiness in Scopes. (Closed)
Patch Set: Created 10 years, 3 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
« no previous file with comments | « src/full-codegen.cc ('k') | src/ia32/full-codegen-ia32.cc » ('j') | 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 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/full-codegen.cc ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698