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 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 // Note that iteration order is relevant here! If we have the same | 241 // Note that iteration order is relevant here! If we have the same |
242 // parameter twice (e.g., function (x, y, x)), and that parameter | 242 // parameter twice (e.g., function (x, y, x)), and that parameter |
243 // needs to be copied into the context, it must be the last argument | 243 // needs to be copied into the context, it must be the last argument |
244 // passed to the parameter that needs to be copied. This is a rare | 244 // passed to the parameter that needs to be copied. This is a rare |
245 // case so we don't check for it, instead we rely on the copying | 245 // case so we don't check for it, instead we rely on the copying |
246 // order: such a parameter is copied repeatedly into the same | 246 // order: such a parameter is copied repeatedly into the same |
247 // context location and thus the last value is what is seen inside | 247 // context location and thus the last value is what is seen inside |
248 // the function. | 248 // the function. |
249 for (int i = 0; i < scope()->num_parameters(); i++) { | 249 for (int i = 0; i < scope()->num_parameters(); i++) { |
250 Variable* par = scope()->parameter(i); | 250 Variable* par = scope()->parameter(i); |
251 Slot* slot = par->slot(); | 251 Slot* slot = par->AsSlot(); |
252 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 252 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
253 // The use of SlotOperand below is safe in unspilled code | 253 // The use of SlotOperand below is safe in unspilled code |
254 // because the slot is guaranteed to be a context slot. | 254 // because the slot is guaranteed to be a context slot. |
255 // | 255 // |
256 // There are no parameters in the global scope. | 256 // There are no parameters in the global scope. |
257 ASSERT(!scope()->is_global_scope()); | 257 ASSERT(!scope()->is_global_scope()); |
258 frame_->PushParameterAt(i); | 258 frame_->PushParameterAt(i); |
259 Result value = frame_->Pop(); | 259 Result value = frame_->Pop(); |
260 value.ToRegister(); | 260 value.ToRegister(); |
261 | 261 |
(...skipping 15 matching lines...) Expand all Loading... |
277 // Store the arguments object. This must happen after context | 277 // Store the arguments object. This must happen after context |
278 // initialization because the arguments object may be stored in | 278 // initialization because the arguments object may be stored in |
279 // the context. | 279 // the context. |
280 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { | 280 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { |
281 StoreArgumentsObject(true); | 281 StoreArgumentsObject(true); |
282 } | 282 } |
283 | 283 |
284 // Initialize ThisFunction reference if present. | 284 // Initialize ThisFunction reference if present. |
285 if (scope()->is_function_scope() && scope()->function() != NULL) { | 285 if (scope()->is_function_scope() && scope()->function() != NULL) { |
286 frame_->Push(Factory::the_hole_value()); | 286 frame_->Push(Factory::the_hole_value()); |
287 StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT); | 287 StoreToSlot(scope()->function()->AsSlot(), NOT_CONST_INIT); |
288 } | 288 } |
289 | 289 |
290 // Initialize the function return target after the locals are set | 290 // Initialize the function return target after the locals are set |
291 // up, because it needs the expected frame height from the frame. | 291 // up, because it needs the expected frame height from the frame. |
292 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); | 292 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); |
293 function_return_is_shadowed_ = false; | 293 function_return_is_shadowed_ = false; |
294 | 294 |
295 // Generate code to 'execute' declarations and initialize functions | 295 // Generate code to 'execute' declarations and initialize functions |
296 // (source elements). In case of an illegal redeclaration we need to | 296 // (source elements). In case of an illegal redeclaration we need to |
297 // handle that instead of processing the declarations. | 297 // handle that instead of processing the declarations. |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 Variable* variable = expr->AsVariableProxy()->AsVariable(); | 594 Variable* variable = expr->AsVariableProxy()->AsVariable(); |
595 if (variable != NULL && !variable->is_this() && variable->is_global()) { | 595 if (variable != NULL && !variable->is_this() && variable->is_global()) { |
596 // For a global variable we build the property reference | 596 // For a global variable we build the property reference |
597 // <global>.<variable> and perform a (regular non-contextual) property | 597 // <global>.<variable> and perform a (regular non-contextual) property |
598 // load to make sure we do not get reference errors. | 598 // load to make sure we do not get reference errors. |
599 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 599 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); |
600 Literal key(variable->name()); | 600 Literal key(variable->name()); |
601 Property property(&global, &key, RelocInfo::kNoPosition); | 601 Property property(&global, &key, RelocInfo::kNoPosition); |
602 Reference ref(this, &property); | 602 Reference ref(this, &property); |
603 ref.GetValue(); | 603 ref.GetValue(); |
604 } else if (variable != NULL && variable->slot() != NULL) { | 604 } else if (variable != NULL && variable->AsSlot() != NULL) { |
605 // For a variable that rewrites to a slot, we signal it is the immediate | 605 // For a variable that rewrites to a slot, we signal it is the immediate |
606 // subexpression of a typeof. | 606 // subexpression of a typeof. |
607 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); | 607 LoadFromSlotCheckForArguments(variable->AsSlot(), INSIDE_TYPEOF); |
608 } else { | 608 } else { |
609 // Anything else can be handled normally. | 609 // Anything else can be handled normally. |
610 Load(expr); | 610 Load(expr); |
611 } | 611 } |
612 } | 612 } |
613 | 613 |
614 | 614 |
615 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { | 615 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { |
616 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; | 616 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; |
617 ASSERT(scope()->arguments_shadow() != NULL); | 617 ASSERT(scope()->arguments_shadow() != NULL); |
(...skipping 18 matching lines...) Expand all Loading... |
636 frame_->Push(Factory::the_hole_value()); | 636 frame_->Push(Factory::the_hole_value()); |
637 } else { | 637 } else { |
638 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | 638 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
639 frame_->PushFunction(); | 639 frame_->PushFunction(); |
640 frame_->PushReceiverSlotAddress(); | 640 frame_->PushReceiverSlotAddress(); |
641 frame_->Push(Smi::FromInt(scope()->num_parameters())); | 641 frame_->Push(Smi::FromInt(scope()->num_parameters())); |
642 Result result = frame_->CallStub(&stub, 3); | 642 Result result = frame_->CallStub(&stub, 3); |
643 frame_->Push(&result); | 643 frame_->Push(&result); |
644 } | 644 } |
645 | 645 |
646 Variable* arguments = scope()->arguments()->var(); | 646 Variable* arguments = scope()->arguments(); |
647 Variable* shadow = scope()->arguments_shadow()->var(); | 647 Variable* shadow = scope()->arguments_shadow(); |
648 ASSERT(arguments != NULL && arguments->slot() != NULL); | 648 ASSERT(arguments != NULL && arguments->AsSlot() != NULL); |
649 ASSERT(shadow != NULL && shadow->slot() != NULL); | 649 ASSERT(shadow != NULL && shadow->AsSlot() != NULL); |
650 JumpTarget done; | 650 JumpTarget done; |
651 bool skip_arguments = false; | 651 bool skip_arguments = false; |
652 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { | 652 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { |
653 // We have to skip storing into the arguments slot if it has | 653 // We have to skip storing into the arguments slot if it has |
654 // already been written to. This can happen if the a function | 654 // already been written to. This can happen if the a function |
655 // has a local variable named 'arguments'. | 655 // has a local variable named 'arguments'. |
656 LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF); | 656 LoadFromSlot(arguments->AsSlot(), NOT_INSIDE_TYPEOF); |
657 Result probe = frame_->Pop(); | 657 Result probe = frame_->Pop(); |
658 if (probe.is_constant()) { | 658 if (probe.is_constant()) { |
659 // We have to skip updating the arguments object if it has | 659 // We have to skip updating the arguments object if it has |
660 // been assigned a proper value. | 660 // been assigned a proper value. |
661 skip_arguments = !probe.handle()->IsTheHole(); | 661 skip_arguments = !probe.handle()->IsTheHole(); |
662 } else { | 662 } else { |
663 __ CompareRoot(probe.reg(), Heap::kTheHoleValueRootIndex); | 663 __ CompareRoot(probe.reg(), Heap::kTheHoleValueRootIndex); |
664 probe.Unuse(); | 664 probe.Unuse(); |
665 done.Branch(not_equal); | 665 done.Branch(not_equal); |
666 } | 666 } |
667 } | 667 } |
668 if (!skip_arguments) { | 668 if (!skip_arguments) { |
669 StoreToSlot(arguments->slot(), NOT_CONST_INIT); | 669 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT); |
670 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); | 670 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); |
671 } | 671 } |
672 StoreToSlot(shadow->slot(), NOT_CONST_INIT); | 672 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT); |
673 return frame_->Pop(); | 673 return frame_->Pop(); |
674 } | 674 } |
675 | 675 |
676 //------------------------------------------------------------------------------ | 676 //------------------------------------------------------------------------------ |
677 // CodeGenerator implementation of variables, lookups, and stores. | 677 // CodeGenerator implementation of variables, lookups, and stores. |
678 | 678 |
679 Reference::Reference(CodeGenerator* cgen, | 679 Reference::Reference(CodeGenerator* cgen, |
680 Expression* expression, | 680 Expression* expression, |
681 bool persist_after_get) | 681 bool persist_after_get) |
682 : cgen_(cgen), | 682 : cgen_(cgen), |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 // property. Global variables are treated as named property references. | 719 // property. Global variables are treated as named property references. |
720 if (var->is_global()) { | 720 if (var->is_global()) { |
721 // If rax is free, the register allocator prefers it. Thus the code | 721 // If rax is free, the register allocator prefers it. Thus the code |
722 // generator will load the global object into rax, which is where | 722 // generator will load the global object into rax, which is where |
723 // LoadIC wants it. Most uses of Reference call LoadIC directly | 723 // LoadIC wants it. Most uses of Reference call LoadIC directly |
724 // after the reference is created. | 724 // after the reference is created. |
725 frame_->Spill(rax); | 725 frame_->Spill(rax); |
726 LoadGlobal(); | 726 LoadGlobal(); |
727 ref->set_type(Reference::NAMED); | 727 ref->set_type(Reference::NAMED); |
728 } else { | 728 } else { |
729 ASSERT(var->slot() != NULL); | 729 ASSERT(var->AsSlot() != NULL); |
730 ref->set_type(Reference::SLOT); | 730 ref->set_type(Reference::SLOT); |
731 } | 731 } |
732 } else { | 732 } else { |
733 // Anything else is a runtime error. | 733 // Anything else is a runtime error. |
734 Load(e); | 734 Load(e); |
735 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); | 735 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); |
736 } | 736 } |
737 | 737 |
738 in_spilled_code_ = was_in_spilled_code; | 738 in_spilled_code_ = was_in_spilled_code; |
739 } | 739 } |
(...skipping 1749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2489 frame()->Dup(); | 2489 frame()->Dup(); |
2490 Handle<String> name = Factory::LookupAsciiSymbol("apply"); | 2490 Handle<String> name = Factory::LookupAsciiSymbol("apply"); |
2491 frame()->Push(name); | 2491 frame()->Push(name); |
2492 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); | 2492 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); |
2493 __ nop(); | 2493 __ nop(); |
2494 frame()->Push(&answer); | 2494 frame()->Push(&answer); |
2495 | 2495 |
2496 // Load the receiver and the existing arguments object onto the | 2496 // Load the receiver and the existing arguments object onto the |
2497 // expression stack. Avoid allocating the arguments object here. | 2497 // expression stack. Avoid allocating the arguments object here. |
2498 Load(receiver); | 2498 Load(receiver); |
2499 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); | 2499 LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF); |
2500 | 2500 |
2501 // Emit the source position information after having loaded the | 2501 // Emit the source position information after having loaded the |
2502 // receiver and the arguments. | 2502 // receiver and the arguments. |
2503 CodeForSourcePosition(position); | 2503 CodeForSourcePosition(position); |
2504 // Contents of frame at this point: | 2504 // Contents of frame at this point: |
2505 // Frame[0]: arguments object of the current function or the hole. | 2505 // Frame[0]: arguments object of the current function or the hole. |
2506 // Frame[1]: receiver | 2506 // Frame[1]: receiver |
2507 // Frame[2]: applicand.apply | 2507 // Frame[2]: applicand.apply |
2508 // Frame[3]: applicand. | 2508 // Frame[3]: applicand. |
2509 | 2509 |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2750 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0)); | 2750 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0)); |
2751 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | 2751 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); |
2752 // Return value is ignored. | 2752 // Return value is ignored. |
2753 } | 2753 } |
2754 | 2754 |
2755 | 2755 |
2756 void CodeGenerator::VisitDeclaration(Declaration* node) { | 2756 void CodeGenerator::VisitDeclaration(Declaration* node) { |
2757 Comment cmnt(masm_, "[ Declaration"); | 2757 Comment cmnt(masm_, "[ Declaration"); |
2758 Variable* var = node->proxy()->var(); | 2758 Variable* var = node->proxy()->var(); |
2759 ASSERT(var != NULL); // must have been resolved | 2759 ASSERT(var != NULL); // must have been resolved |
2760 Slot* slot = var->slot(); | 2760 Slot* slot = var->AsSlot(); |
2761 | 2761 |
2762 // If it was not possible to allocate the variable at compile time, | 2762 // If it was not possible to allocate the variable at compile time, |
2763 // we need to "declare" it at runtime to make sure it actually | 2763 // we need to "declare" it at runtime to make sure it actually |
2764 // exists in the local context. | 2764 // exists in the local context. |
2765 if (slot != NULL && slot->type() == Slot::LOOKUP) { | 2765 if (slot != NULL && slot->type() == Slot::LOOKUP) { |
2766 // Variables with a "LOOKUP" slot were introduced as non-locals | 2766 // Variables with a "LOOKUP" slot were introduced as non-locals |
2767 // during variable resolution and must have mode DYNAMIC. | 2767 // during variable resolution and must have mode DYNAMIC. |
2768 ASSERT(var->is_dynamic()); | 2768 ASSERT(var->is_dynamic()); |
2769 // For now, just do a runtime call. Sync the virtual frame eagerly | 2769 // For now, just do a runtime call. Sync the virtual frame eagerly |
2770 // so we can simply push the arguments into place. | 2770 // so we can simply push the arguments into place. |
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3428 // Set type and stack height of BreakTargets. | 3428 // Set type and stack height of BreakTargets. |
3429 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); | 3429 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); |
3430 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); | 3430 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
3431 | 3431 |
3432 IncrementLoopNesting(); | 3432 IncrementLoopNesting(); |
3433 loop.Bind(); | 3433 loop.Bind(); |
3434 | 3434 |
3435 // Set number type of the loop variable to smi. | 3435 // Set number type of the loop variable to smi. |
3436 CheckStack(); // TODO(1222600): ignore if body contains calls. | 3436 CheckStack(); // TODO(1222600): ignore if body contains calls. |
3437 | 3437 |
3438 SetTypeForStackSlot(loop_var->slot(), TypeInfo::Smi()); | 3438 SetTypeForStackSlot(loop_var->AsSlot(), TypeInfo::Smi()); |
3439 Visit(node->body()); | 3439 Visit(node->body()); |
3440 | 3440 |
3441 if (node->continue_target()->is_linked()) { | 3441 if (node->continue_target()->is_linked()) { |
3442 node->continue_target()->Bind(); | 3442 node->continue_target()->Bind(); |
3443 } | 3443 } |
3444 | 3444 |
3445 if (has_valid_frame()) { | 3445 if (has_valid_frame()) { |
3446 CodeForStatementPosition(node); | 3446 CodeForStatementPosition(node); |
3447 Slot* loop_var_slot = loop_var->slot(); | 3447 Slot* loop_var_slot = loop_var->AsSlot(); |
3448 if (loop_var_slot->type() == Slot::LOCAL) { | 3448 if (loop_var_slot->type() == Slot::LOCAL) { |
3449 frame_->TakeLocalAt(loop_var_slot->index()); | 3449 frame_->TakeLocalAt(loop_var_slot->index()); |
3450 } else { | 3450 } else { |
3451 ASSERT(loop_var_slot->type() == Slot::PARAMETER); | 3451 ASSERT(loop_var_slot->type() == Slot::PARAMETER); |
3452 frame_->TakeParameterAt(loop_var_slot->index()); | 3452 frame_->TakeParameterAt(loop_var_slot->index()); |
3453 } | 3453 } |
3454 Result loop_var_result = frame_->Pop(); | 3454 Result loop_var_result = frame_->Pop(); |
3455 if (!loop_var_result.is_register()) { | 3455 if (!loop_var_result.is_register()) { |
3456 loop_var_result.ToRegister(); | 3456 loop_var_result.ToRegister(); |
3457 } | 3457 } |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3911 | 3911 |
3912 JumpTarget try_block; | 3912 JumpTarget try_block; |
3913 JumpTarget exit; | 3913 JumpTarget exit; |
3914 | 3914 |
3915 try_block.Call(); | 3915 try_block.Call(); |
3916 // --- Catch block --- | 3916 // --- Catch block --- |
3917 frame_->EmitPush(rax); | 3917 frame_->EmitPush(rax); |
3918 | 3918 |
3919 // Store the caught exception in the catch variable. | 3919 // Store the caught exception in the catch variable. |
3920 Variable* catch_var = node->catch_var()->var(); | 3920 Variable* catch_var = node->catch_var()->var(); |
3921 ASSERT(catch_var != NULL && catch_var->slot() != NULL); | 3921 ASSERT(catch_var != NULL && catch_var->AsSlot() != NULL); |
3922 StoreToSlot(catch_var->slot(), NOT_CONST_INIT); | 3922 StoreToSlot(catch_var->AsSlot(), NOT_CONST_INIT); |
3923 | 3923 |
3924 // Remove the exception from the stack. | 3924 // Remove the exception from the stack. |
3925 frame_->Drop(); | 3925 frame_->Drop(); |
3926 | 3926 |
3927 VisitStatementsAndSpill(node->catch_block()->statements()); | 3927 VisitStatementsAndSpill(node->catch_block()->statements()); |
3928 if (has_valid_frame()) { | 3928 if (has_valid_frame()) { |
3929 exit.Jump(); | 3929 exit.Jump(); |
3930 } | 3930 } |
3931 | 3931 |
3932 | 3932 |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4510 // Generate fast-case code for variables that might be shadowed by | 4510 // Generate fast-case code for variables that might be shadowed by |
4511 // eval-introduced variables. Eval is used a lot without | 4511 // eval-introduced variables. Eval is used a lot without |
4512 // introducing variables. In those cases, we do not want to | 4512 // introducing variables. In those cases, we do not want to |
4513 // perform a runtime call for all variables in the scope | 4513 // perform a runtime call for all variables in the scope |
4514 // containing the eval. | 4514 // containing the eval. |
4515 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 4515 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
4516 *result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow); | 4516 *result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow); |
4517 done->Jump(result); | 4517 done->Jump(result); |
4518 | 4518 |
4519 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 4519 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
4520 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | 4520 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); |
4521 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | 4521 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); |
4522 if (potential_slot != NULL) { | 4522 if (potential_slot != NULL) { |
4523 // Generate fast case for locals that rewrite to slots. | 4523 // Generate fast case for locals that rewrite to slots. |
4524 // Allocate a fresh register to use as a temp in | 4524 // Allocate a fresh register to use as a temp in |
4525 // ContextSlotOperandCheckExtensions and to hold the result | 4525 // ContextSlotOperandCheckExtensions and to hold the result |
4526 // value. | 4526 // value. |
4527 *result = allocator_->Allocate(); | 4527 *result = allocator_->Allocate(); |
4528 ASSERT(result->is_valid()); | 4528 ASSERT(result->is_valid()); |
4529 __ movq(result->reg(), | 4529 __ movq(result->reg(), |
4530 ContextSlotOperandCheckExtensions(potential_slot, | 4530 ContextSlotOperandCheckExtensions(potential_slot, |
(...skipping 14 matching lines...) Expand all Loading... |
4545 if (obj_proxy != NULL && | 4545 if (obj_proxy != NULL && |
4546 key_literal != NULL && | 4546 key_literal != NULL && |
4547 obj_proxy->IsArguments() && | 4547 obj_proxy->IsArguments() && |
4548 key_literal->handle()->IsSmi()) { | 4548 key_literal->handle()->IsSmi()) { |
4549 // Load arguments object if there are no eval-introduced | 4549 // Load arguments object if there are no eval-introduced |
4550 // variables. Then load the argument from the arguments | 4550 // variables. Then load the argument from the arguments |
4551 // object using keyed load. | 4551 // object using keyed load. |
4552 Result arguments = allocator()->Allocate(); | 4552 Result arguments = allocator()->Allocate(); |
4553 ASSERT(arguments.is_valid()); | 4553 ASSERT(arguments.is_valid()); |
4554 __ movq(arguments.reg(), | 4554 __ movq(arguments.reg(), |
4555 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | 4555 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
4556 arguments, | 4556 arguments, |
4557 slow)); | 4557 slow)); |
4558 frame_->Push(&arguments); | 4558 frame_->Push(&arguments); |
4559 frame_->Push(key_literal->handle()); | 4559 frame_->Push(key_literal->handle()); |
4560 *result = EmitKeyedLoad(); | 4560 *result = EmitKeyedLoad(); |
4561 done->Jump(result); | 4561 done->Jump(result); |
4562 } | 4562 } |
4563 } | 4563 } |
4564 } | 4564 } |
4565 } | 4565 } |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5011 } | 5011 } |
5012 | 5012 |
5013 | 5013 |
5014 void CodeGenerator::EmitSlotAssignment(Assignment* node) { | 5014 void CodeGenerator::EmitSlotAssignment(Assignment* node) { |
5015 #ifdef DEBUG | 5015 #ifdef DEBUG |
5016 int original_height = frame()->height(); | 5016 int original_height = frame()->height(); |
5017 #endif | 5017 #endif |
5018 Comment cmnt(masm(), "[ Variable Assignment"); | 5018 Comment cmnt(masm(), "[ Variable Assignment"); |
5019 Variable* var = node->target()->AsVariableProxy()->AsVariable(); | 5019 Variable* var = node->target()->AsVariableProxy()->AsVariable(); |
5020 ASSERT(var != NULL); | 5020 ASSERT(var != NULL); |
5021 Slot* slot = var->slot(); | 5021 Slot* slot = var->AsSlot(); |
5022 ASSERT(slot != NULL); | 5022 ASSERT(slot != NULL); |
5023 | 5023 |
5024 // Evaluate the right-hand side. | 5024 // Evaluate the right-hand side. |
5025 if (node->is_compound()) { | 5025 if (node->is_compound()) { |
5026 // For a compound assignment the right-hand side is a binary operation | 5026 // For a compound assignment the right-hand side is a binary operation |
5027 // between the current property value and the actual right-hand side. | 5027 // between the current property value and the actual right-hand side. |
5028 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 5028 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
5029 Load(node->value()); | 5029 Load(node->value()); |
5030 | 5030 |
5031 // Perform the binary operation. | 5031 // Perform the binary operation. |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5356 | 5356 |
5357 // Result to hold the result of the function resolution and the | 5357 // Result to hold the result of the function resolution and the |
5358 // final result of the eval call. | 5358 // final result of the eval call. |
5359 Result result; | 5359 Result result; |
5360 | 5360 |
5361 // If we know that eval can only be shadowed by eval-introduced | 5361 // If we know that eval can only be shadowed by eval-introduced |
5362 // variables we attempt to load the global eval function directly | 5362 // variables we attempt to load the global eval function directly |
5363 // in generated code. If we succeed, there is no need to perform a | 5363 // in generated code. If we succeed, there is no need to perform a |
5364 // context lookup in the runtime system. | 5364 // context lookup in the runtime system. |
5365 JumpTarget done; | 5365 JumpTarget done; |
5366 if (var->slot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { | 5366 if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { |
5367 ASSERT(var->slot()->type() == Slot::LOOKUP); | 5367 ASSERT(var->AsSlot()->type() == Slot::LOOKUP); |
5368 JumpTarget slow; | 5368 JumpTarget slow; |
5369 // Prepare the stack for the call to | 5369 // Prepare the stack for the call to |
5370 // ResolvePossiblyDirectEvalNoLookup by pushing the loaded | 5370 // ResolvePossiblyDirectEvalNoLookup by pushing the loaded |
5371 // function, the first argument to the eval call and the | 5371 // function, the first argument to the eval call and the |
5372 // receiver. | 5372 // receiver. |
5373 Result fun = LoadFromGlobalSlotCheckExtensions(var->slot(), | 5373 Result fun = LoadFromGlobalSlotCheckExtensions(var->AsSlot(), |
5374 NOT_INSIDE_TYPEOF, | 5374 NOT_INSIDE_TYPEOF, |
5375 &slow); | 5375 &slow); |
5376 frame_->Push(&fun); | 5376 frame_->Push(&fun); |
5377 if (arg_count > 0) { | 5377 if (arg_count > 0) { |
5378 frame_->PushElementAt(arg_count); | 5378 frame_->PushElementAt(arg_count); |
5379 } else { | 5379 } else { |
5380 frame_->Push(Factory::undefined_value()); | 5380 frame_->Push(Factory::undefined_value()); |
5381 } | 5381 } |
5382 frame_->PushParameterAt(-1); | 5382 frame_->PushParameterAt(-1); |
5383 | 5383 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5447 | 5447 |
5448 // Call the IC initialization code. | 5448 // Call the IC initialization code. |
5449 CodeForSourcePosition(node->position()); | 5449 CodeForSourcePosition(node->position()); |
5450 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, | 5450 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, |
5451 arg_count, | 5451 arg_count, |
5452 loop_nesting()); | 5452 loop_nesting()); |
5453 frame_->RestoreContextRegister(); | 5453 frame_->RestoreContextRegister(); |
5454 // Replace the function on the stack with the result. | 5454 // Replace the function on the stack with the result. |
5455 frame_->Push(&result); | 5455 frame_->Push(&result); |
5456 | 5456 |
5457 } else if (var != NULL && var->slot() != NULL && | 5457 } else if (var != NULL && var->AsSlot() != NULL && |
5458 var->slot()->type() == Slot::LOOKUP) { | 5458 var->AsSlot()->type() == Slot::LOOKUP) { |
5459 // ---------------------------------- | 5459 // ---------------------------------- |
5460 // JavaScript examples: | 5460 // JavaScript examples: |
5461 // | 5461 // |
5462 // with (obj) foo(1, 2, 3) // foo may be in obj. | 5462 // with (obj) foo(1, 2, 3) // foo may be in obj. |
5463 // | 5463 // |
5464 // function f() {}; | 5464 // function f() {}; |
5465 // function g() { | 5465 // function g() { |
5466 // eval(...); | 5466 // eval(...); |
5467 // f(); // f could be in extension object. | 5467 // f(); // f could be in extension object. |
5468 // } | 5468 // } |
5469 // ---------------------------------- | 5469 // ---------------------------------- |
5470 | 5470 |
5471 JumpTarget slow, done; | 5471 JumpTarget slow, done; |
5472 Result function; | 5472 Result function; |
5473 | 5473 |
5474 // Generate fast case for loading functions from slots that | 5474 // Generate fast case for loading functions from slots that |
5475 // correspond to local/global variables or arguments unless they | 5475 // correspond to local/global variables or arguments unless they |
5476 // are shadowed by eval-introduced bindings. | 5476 // are shadowed by eval-introduced bindings. |
5477 EmitDynamicLoadFromSlotFastCase(var->slot(), | 5477 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
5478 NOT_INSIDE_TYPEOF, | 5478 NOT_INSIDE_TYPEOF, |
5479 &function, | 5479 &function, |
5480 &slow, | 5480 &slow, |
5481 &done); | 5481 &done); |
5482 | 5482 |
5483 slow.Bind(); | 5483 slow.Bind(); |
5484 // Load the function from the context. Sync the frame so we can | 5484 // Load the function from the context. Sync the frame so we can |
5485 // push the arguments directly into place. | 5485 // push the arguments directly into place. |
5486 frame_->SyncRange(0, frame_->element_count() - 1); | 5486 frame_->SyncRange(0, frame_->element_count() - 1); |
5487 frame_->EmitPush(rsi); | 5487 frame_->EmitPush(rsi); |
(...skipping 1842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7330 if (property != NULL) { | 7330 if (property != NULL) { |
7331 Load(property->obj()); | 7331 Load(property->obj()); |
7332 Load(property->key()); | 7332 Load(property->key()); |
7333 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); | 7333 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); |
7334 frame_->Push(&answer); | 7334 frame_->Push(&answer); |
7335 return; | 7335 return; |
7336 } | 7336 } |
7337 | 7337 |
7338 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 7338 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
7339 if (variable != NULL) { | 7339 if (variable != NULL) { |
7340 Slot* slot = variable->slot(); | 7340 Slot* slot = variable->AsSlot(); |
7341 if (variable->is_global()) { | 7341 if (variable->is_global()) { |
7342 LoadGlobal(); | 7342 LoadGlobal(); |
7343 frame_->Push(variable->name()); | 7343 frame_->Push(variable->name()); |
7344 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, | 7344 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, |
7345 CALL_FUNCTION, 2); | 7345 CALL_FUNCTION, 2); |
7346 frame_->Push(&answer); | 7346 frame_->Push(&answer); |
7347 return; | 7347 return; |
7348 | 7348 |
7349 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 7349 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
7350 // Call the runtime to look up the context holding the named | 7350 // Call the runtime to look up the context holding the named |
(...skipping 1335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8686 | 8686 |
8687 // Record the source position for the property load. | 8687 // Record the source position for the property load. |
8688 Property* property = expression_->AsProperty(); | 8688 Property* property = expression_->AsProperty(); |
8689 if (property != NULL) { | 8689 if (property != NULL) { |
8690 cgen_->CodeForSourcePosition(property->position()); | 8690 cgen_->CodeForSourcePosition(property->position()); |
8691 } | 8691 } |
8692 | 8692 |
8693 switch (type_) { | 8693 switch (type_) { |
8694 case SLOT: { | 8694 case SLOT: { |
8695 Comment cmnt(masm, "[ Load from Slot"); | 8695 Comment cmnt(masm, "[ Load from Slot"); |
8696 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 8696 Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot(); |
8697 ASSERT(slot != NULL); | 8697 ASSERT(slot != NULL); |
8698 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 8698 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
8699 break; | 8699 break; |
8700 } | 8700 } |
8701 | 8701 |
8702 case NAMED: { | 8702 case NAMED: { |
8703 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 8703 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
8704 bool is_global = var != NULL; | 8704 bool is_global = var != NULL; |
8705 ASSERT(!is_global || var->is_global()); | 8705 ASSERT(!is_global || var->is_global()); |
8706 if (persist_after_get_) { | 8706 if (persist_after_get_) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8739 | 8739 |
8740 // For non-constant frame-allocated slots, we invalidate the value in the | 8740 // For non-constant frame-allocated slots, we invalidate the value in the |
8741 // slot. For all others, we fall back on GetValue. | 8741 // slot. For all others, we fall back on GetValue. |
8742 ASSERT(!cgen_->in_spilled_code()); | 8742 ASSERT(!cgen_->in_spilled_code()); |
8743 ASSERT(!is_illegal()); | 8743 ASSERT(!is_illegal()); |
8744 if (type_ != SLOT) { | 8744 if (type_ != SLOT) { |
8745 GetValue(); | 8745 GetValue(); |
8746 return; | 8746 return; |
8747 } | 8747 } |
8748 | 8748 |
8749 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 8749 Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot(); |
8750 ASSERT(slot != NULL); | 8750 ASSERT(slot != NULL); |
8751 if (slot->type() == Slot::LOOKUP || | 8751 if (slot->type() == Slot::LOOKUP || |
8752 slot->type() == Slot::CONTEXT || | 8752 slot->type() == Slot::CONTEXT || |
8753 slot->var()->mode() == Variable::CONST || | 8753 slot->var()->mode() == Variable::CONST || |
8754 slot->is_arguments()) { | 8754 slot->is_arguments()) { |
8755 GetValue(); | 8755 GetValue(); |
8756 return; | 8756 return; |
8757 } | 8757 } |
8758 | 8758 |
8759 // Only non-constant, frame-allocated parameters and locals can reach | 8759 // Only non-constant, frame-allocated parameters and locals can reach |
(...skipping 12 matching lines...) Expand all Loading... |
8772 } | 8772 } |
8773 | 8773 |
8774 | 8774 |
8775 void Reference::SetValue(InitState init_state) { | 8775 void Reference::SetValue(InitState init_state) { |
8776 ASSERT(cgen_->HasValidEntryRegisters()); | 8776 ASSERT(cgen_->HasValidEntryRegisters()); |
8777 ASSERT(!is_illegal()); | 8777 ASSERT(!is_illegal()); |
8778 MacroAssembler* masm = cgen_->masm(); | 8778 MacroAssembler* masm = cgen_->masm(); |
8779 switch (type_) { | 8779 switch (type_) { |
8780 case SLOT: { | 8780 case SLOT: { |
8781 Comment cmnt(masm, "[ Store to Slot"); | 8781 Comment cmnt(masm, "[ Store to Slot"); |
8782 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 8782 Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot(); |
8783 ASSERT(slot != NULL); | 8783 ASSERT(slot != NULL); |
8784 cgen_->StoreToSlot(slot, init_state); | 8784 cgen_->StoreToSlot(slot, init_state); |
8785 set_unloaded(); | 8785 set_unloaded(); |
8786 break; | 8786 break; |
8787 } | 8787 } |
8788 | 8788 |
8789 case NAMED: { | 8789 case NAMED: { |
8790 Comment cmnt(masm, "[ Store to named Property"); | 8790 Comment cmnt(masm, "[ Store to named Property"); |
8791 Result answer = cgen_->EmitNamedStore(GetName(), false); | 8791 Result answer = cgen_->EmitNamedStore(GetName(), false); |
8792 cgen_->frame()->Push(&answer); | 8792 cgen_->frame()->Push(&answer); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8922 #undef __ | 8922 #undef __ |
8923 | 8923 |
8924 void RecordWriteStub::Generate(MacroAssembler* masm) { | 8924 void RecordWriteStub::Generate(MacroAssembler* masm) { |
8925 masm->RecordWriteHelper(object_, addr_, scratch_); | 8925 masm->RecordWriteHelper(object_, addr_, scratch_); |
8926 masm->ret(0); | 8926 masm->ret(0); |
8927 } | 8927 } |
8928 | 8928 |
8929 } } // namespace v8::internal | 8929 } } // namespace v8::internal |
8930 | 8930 |
8931 #endif // V8_TARGET_ARCH_X64 | 8931 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |