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

Side by Side Diff: src/x64/codegen-x64.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/variables.cc ('k') | src/x64/full-codegen-x64.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 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/variables.cc ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698