| 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 |