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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 __ CallRuntime(Runtime::kNewContext, 1); | 93 __ CallRuntime(Runtime::kNewContext, 1); |
94 } | 94 } |
95 function_in_register = false; | 95 function_in_register = false; |
96 // Context is returned in both rax and rsi. It replaces the context | 96 // Context is returned in both rax and rsi. It replaces the context |
97 // passed to us. It's saved in the stack and kept live in rsi. | 97 // passed to us. It's saved in the stack and kept live in rsi. |
98 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); | 98 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); |
99 | 99 |
100 // Copy any necessary parameters into the context. | 100 // Copy any necessary parameters into the context. |
101 int num_parameters = scope()->num_parameters(); | 101 int num_parameters = scope()->num_parameters(); |
102 for (int i = 0; i < num_parameters; i++) { | 102 for (int i = 0; i < num_parameters; i++) { |
103 Slot* slot = scope()->parameter(i)->slot(); | 103 Slot* slot = scope()->parameter(i)->AsSlot(); |
104 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 104 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
105 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 105 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
106 (num_parameters - 1 - i) * kPointerSize; | 106 (num_parameters - 1 - i) * kPointerSize; |
107 // Load parameter from stack. | 107 // Load parameter from stack. |
108 __ movq(rax, Operand(rbp, parameter_offset)); | 108 __ movq(rax, Operand(rbp, parameter_offset)); |
109 // Store it in the context. | 109 // Store it in the context. |
110 int context_offset = Context::SlotOffset(slot->index()); | 110 int context_offset = Context::SlotOffset(slot->index()); |
111 __ movq(Operand(rsi, context_offset), rax); | 111 __ movq(Operand(rsi, context_offset), rax); |
112 // Update the write barrier. This clobbers all involved | 112 // Update the write barrier. This clobbers all involved |
113 // registers, so we have use a third register to avoid | 113 // registers, so we have use a third register to avoid |
114 // clobbering rsi. | 114 // clobbering rsi. |
115 __ movq(rcx, rsi); | 115 __ movq(rcx, rsi); |
116 __ RecordWrite(rcx, context_offset, rax, rbx); | 116 __ RecordWrite(rcx, context_offset, rax, rbx); |
117 } | 117 } |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 // Possibly allocate an arguments object. | 121 // Possibly allocate an arguments object. |
122 Variable* arguments = scope()->arguments()->AsVariable(); | 122 Variable* arguments = scope()->arguments(); |
123 if (arguments != NULL) { | 123 if (arguments != NULL) { |
124 // Arguments object must be allocated after the context object, in | 124 // Arguments object must be allocated after the context object, in |
125 // case the "arguments" or ".arguments" variables are in the context. | 125 // case the "arguments" or ".arguments" variables are in the context. |
126 Comment cmnt(masm_, "[ Allocate arguments object"); | 126 Comment cmnt(masm_, "[ Allocate arguments object"); |
127 if (function_in_register) { | 127 if (function_in_register) { |
128 __ push(rdi); | 128 __ push(rdi); |
129 } else { | 129 } else { |
130 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 130 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
131 } | 131 } |
132 // The receiver is just before the parameters on the caller's stack. | 132 // The receiver is just before the parameters on the caller's stack. |
133 int offset = scope()->num_parameters() * kPointerSize; | 133 int offset = scope()->num_parameters() * kPointerSize; |
134 __ lea(rdx, | 134 __ lea(rdx, |
135 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); | 135 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); |
136 __ push(rdx); | 136 __ push(rdx); |
137 __ Push(Smi::FromInt(scope()->num_parameters())); | 137 __ Push(Smi::FromInt(scope()->num_parameters())); |
138 // Arguments to ArgumentsAccessStub: | 138 // Arguments to ArgumentsAccessStub: |
139 // function, receiver address, parameter count. | 139 // function, receiver address, parameter count. |
140 // The stub will rewrite receiver and parameter count if the previous | 140 // The stub will rewrite receiver and parameter count if the previous |
141 // stack frame was an arguments adapter frame. | 141 // stack frame was an arguments adapter frame. |
142 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | 142 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
143 __ CallStub(&stub); | 143 __ CallStub(&stub); |
144 // Store new arguments object in both "arguments" and ".arguments" slots. | 144 // Store new arguments object in both "arguments" and ".arguments" slots. |
145 __ movq(rcx, rax); | 145 __ movq(rcx, rax); |
146 Move(arguments->slot(), rax, rbx, rdx); | 146 Move(arguments->AsSlot(), rax, rbx, rdx); |
147 Slot* dot_arguments_slot = | 147 Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot(); |
148 scope()->arguments_shadow()->AsVariable()->slot(); | |
149 Move(dot_arguments_slot, rcx, rbx, rdx); | 148 Move(dot_arguments_slot, rcx, rbx, rdx); |
150 } | 149 } |
151 | 150 |
152 { Comment cmnt(masm_, "[ Declarations"); | 151 { Comment cmnt(masm_, "[ Declarations"); |
153 // For named function expressions, declare the function name as a | 152 // For named function expressions, declare the function name as a |
154 // constant. | 153 // constant. |
155 if (scope()->is_function_scope() && scope()->function() != NULL) { | 154 if (scope()->is_function_scope() && scope()->function() != NULL) { |
156 EmitDeclaration(scope()->function(), Variable::CONST, NULL); | 155 EmitDeclaration(scope()->function(), Variable::CONST, NULL); |
157 } | 156 } |
158 // Visit all the explicit declarations unless there is an illegal | 157 // Visit all the explicit declarations unless there is an illegal |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 __ RecordWrite(scratch1, offset, src, scratch2); | 511 __ RecordWrite(scratch1, offset, src, scratch2); |
513 } | 512 } |
514 } | 513 } |
515 | 514 |
516 | 515 |
517 void FullCodeGenerator::EmitDeclaration(Variable* variable, | 516 void FullCodeGenerator::EmitDeclaration(Variable* variable, |
518 Variable::Mode mode, | 517 Variable::Mode mode, |
519 FunctionLiteral* function) { | 518 FunctionLiteral* function) { |
520 Comment cmnt(masm_, "[ Declaration"); | 519 Comment cmnt(masm_, "[ Declaration"); |
521 ASSERT(variable != NULL); // Must have been resolved. | 520 ASSERT(variable != NULL); // Must have been resolved. |
522 Slot* slot = variable->slot(); | 521 Slot* slot = variable->AsSlot(); |
523 Property* prop = variable->AsProperty(); | 522 Property* prop = variable->AsProperty(); |
524 | 523 |
525 if (slot != NULL) { | 524 if (slot != NULL) { |
526 switch (slot->type()) { | 525 switch (slot->type()) { |
527 case Slot::PARAMETER: | 526 case Slot::PARAMETER: |
528 case Slot::LOCAL: | 527 case Slot::LOCAL: |
529 if (mode == Variable::CONST) { | 528 if (mode == Variable::CONST) { |
530 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 529 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
531 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); | 530 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); |
532 } else if (function != NULL) { | 531 } else if (function != NULL) { |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 Label* done) { | 952 Label* done) { |
954 // Generate fast-case code for variables that might be shadowed by | 953 // Generate fast-case code for variables that might be shadowed by |
955 // eval-introduced variables. Eval is used a lot without | 954 // eval-introduced variables. Eval is used a lot without |
956 // introducing variables. In those cases, we do not want to | 955 // introducing variables. In those cases, we do not want to |
957 // perform a runtime call for all variables in the scope | 956 // perform a runtime call for all variables in the scope |
958 // containing the eval. | 957 // containing the eval. |
959 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 958 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
960 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); | 959 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); |
961 __ jmp(done); | 960 __ jmp(done); |
962 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 961 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
963 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | 962 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); |
964 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | 963 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); |
965 if (potential_slot != NULL) { | 964 if (potential_slot != NULL) { |
966 // Generate fast case for locals that rewrite to slots. | 965 // Generate fast case for locals that rewrite to slots. |
967 __ movq(rax, | 966 __ movq(rax, |
968 ContextSlotOperandCheckExtensions(potential_slot, slow)); | 967 ContextSlotOperandCheckExtensions(potential_slot, slow)); |
969 if (potential_slot->var()->mode() == Variable::CONST) { | 968 if (potential_slot->var()->mode() == Variable::CONST) { |
970 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 969 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
971 __ j(not_equal, done); | 970 __ j(not_equal, done); |
972 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 971 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
973 } | 972 } |
974 __ jmp(done); | 973 __ jmp(done); |
975 } else if (rewrite != NULL) { | 974 } else if (rewrite != NULL) { |
976 // Generate fast case for calls of an argument function. | 975 // Generate fast case for calls of an argument function. |
977 Property* property = rewrite->AsProperty(); | 976 Property* property = rewrite->AsProperty(); |
978 if (property != NULL) { | 977 if (property != NULL) { |
979 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | 978 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); |
980 Literal* key_literal = property->key()->AsLiteral(); | 979 Literal* key_literal = property->key()->AsLiteral(); |
981 if (obj_proxy != NULL && | 980 if (obj_proxy != NULL && |
982 key_literal != NULL && | 981 key_literal != NULL && |
983 obj_proxy->IsArguments() && | 982 obj_proxy->IsArguments() && |
984 key_literal->handle()->IsSmi()) { | 983 key_literal->handle()->IsSmi()) { |
985 // Load arguments object if there are no eval-introduced | 984 // Load arguments object if there are no eval-introduced |
986 // variables. Then load the argument from the arguments | 985 // variables. Then load the argument from the arguments |
987 // object using keyed load. | 986 // object using keyed load. |
988 __ movq(rdx, | 987 __ movq(rdx, |
989 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | 988 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
990 slow)); | 989 slow)); |
991 __ Move(rax, key_literal->handle()); | 990 __ Move(rax, key_literal->handle()); |
992 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 991 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
993 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 992 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
994 __ jmp(done); | 993 __ jmp(done); |
995 } | 994 } |
996 } | 995 } |
997 } | 996 } |
998 } | 997 } |
999 } | 998 } |
1000 | 999 |
1001 | 1000 |
1002 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1001 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
1003 // Four cases: non-this global variables, lookup slots, all other | 1002 // Four cases: non-this global variables, lookup slots, all other |
1004 // types of slots, and parameters that rewrite to explicit property | 1003 // types of slots, and parameters that rewrite to explicit property |
1005 // accesses on the arguments object. | 1004 // accesses on the arguments object. |
1006 Slot* slot = var->slot(); | 1005 Slot* slot = var->AsSlot(); |
1007 Property* property = var->AsProperty(); | 1006 Property* property = var->AsProperty(); |
1008 | 1007 |
1009 if (var->is_global() && !var->is_this()) { | 1008 if (var->is_global() && !var->is_this()) { |
1010 Comment cmnt(masm_, "Global variable"); | 1009 Comment cmnt(masm_, "Global variable"); |
1011 // Use inline caching. Variable name is passed in rcx and the global | 1010 // Use inline caching. Variable name is passed in rcx and the global |
1012 // object on the stack. | 1011 // object on the stack. |
1013 __ Move(rcx, var->name()); | 1012 __ Move(rcx, var->name()); |
1014 __ movq(rax, CodeGenerator::GlobalObject()); | 1013 __ movq(rax, CodeGenerator::GlobalObject()); |
1015 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1014 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1016 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1015 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 } | 1051 } |
1053 | 1052 |
1054 } else { | 1053 } else { |
1055 Comment cmnt(masm_, "Rewritten parameter"); | 1054 Comment cmnt(masm_, "Rewritten parameter"); |
1056 ASSERT_NOT_NULL(property); | 1055 ASSERT_NOT_NULL(property); |
1057 // Rewritten parameter accesses are of the form "slot[literal]". | 1056 // Rewritten parameter accesses are of the form "slot[literal]". |
1058 | 1057 |
1059 // Assert that the object is in a slot. | 1058 // Assert that the object is in a slot. |
1060 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); | 1059 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); |
1061 ASSERT_NOT_NULL(object_var); | 1060 ASSERT_NOT_NULL(object_var); |
1062 Slot* object_slot = object_var->slot(); | 1061 Slot* object_slot = object_var->AsSlot(); |
1063 ASSERT_NOT_NULL(object_slot); | 1062 ASSERT_NOT_NULL(object_slot); |
1064 | 1063 |
1065 // Load the object. | 1064 // Load the object. |
1066 MemOperand object_loc = EmitSlotSearch(object_slot, rax); | 1065 MemOperand object_loc = EmitSlotSearch(object_slot, rax); |
1067 __ movq(rdx, object_loc); | 1066 __ movq(rdx, object_loc); |
1068 | 1067 |
1069 // Assert that the key is a smi. | 1068 // Assert that the key is a smi. |
1070 Literal* key_literal = property->key()->AsLiteral(); | 1069 Literal* key_literal = property->key()->AsLiteral(); |
1071 ASSERT_NOT_NULL(key_literal); | 1070 ASSERT_NOT_NULL(key_literal); |
1072 ASSERT(key_literal->handle()->IsSmi()); | 1071 ASSERT(key_literal->handle()->IsSmi()); |
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1524 } | 1523 } |
1525 } | 1524 } |
1526 } | 1525 } |
1527 | 1526 |
1528 | 1527 |
1529 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1528 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1530 Token::Value op) { | 1529 Token::Value op) { |
1531 // Left-hand sides that rewrite to explicit property accesses do not reach | 1530 // Left-hand sides that rewrite to explicit property accesses do not reach |
1532 // here. | 1531 // here. |
1533 ASSERT(var != NULL); | 1532 ASSERT(var != NULL); |
1534 ASSERT(var->is_global() || var->slot() != NULL); | 1533 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1535 | 1534 |
1536 if (var->is_global()) { | 1535 if (var->is_global()) { |
1537 ASSERT(!var->is_this()); | 1536 ASSERT(!var->is_this()); |
1538 // Assignment to a global variable. Use inline caching for the | 1537 // Assignment to a global variable. Use inline caching for the |
1539 // assignment. Right-hand-side value is passed in rax, variable name in | 1538 // assignment. Right-hand-side value is passed in rax, variable name in |
1540 // rcx, and the global object on the stack. | 1539 // rcx, and the global object on the stack. |
1541 __ Move(rcx, var->name()); | 1540 __ Move(rcx, var->name()); |
1542 __ movq(rdx, CodeGenerator::GlobalObject()); | 1541 __ movq(rdx, CodeGenerator::GlobalObject()); |
1543 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1542 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1544 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1543 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1545 | 1544 |
1546 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { | 1545 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { |
1547 // Perform the assignment for non-const variables and for initialization | 1546 // Perform the assignment for non-const variables and for initialization |
1548 // of const variables. Const assignments are simply skipped. | 1547 // of const variables. Const assignments are simply skipped. |
1549 Label done; | 1548 Label done; |
1550 Slot* slot = var->slot(); | 1549 Slot* slot = var->AsSlot(); |
1551 switch (slot->type()) { | 1550 switch (slot->type()) { |
1552 case Slot::PARAMETER: | 1551 case Slot::PARAMETER: |
1553 case Slot::LOCAL: | 1552 case Slot::LOCAL: |
1554 if (op == Token::INIT_CONST) { | 1553 if (op == Token::INIT_CONST) { |
1555 // Detect const reinitialization by checking for the hole value. | 1554 // Detect const reinitialization by checking for the hole value. |
1556 __ movq(rdx, Operand(rbp, SlotOffset(slot))); | 1555 __ movq(rdx, Operand(rbp, SlotOffset(slot))); |
1557 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 1556 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
1558 __ j(not_equal, &done); | 1557 __ j(not_equal, &done); |
1559 } | 1558 } |
1560 // Perform the assignment. | 1559 // Perform the assignment. |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1806 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 1805 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
1807 __ CallStub(&stub); | 1806 __ CallStub(&stub); |
1808 // Restore context register. | 1807 // Restore context register. |
1809 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1808 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1810 context()->DropAndPlug(1, rax); | 1809 context()->DropAndPlug(1, rax); |
1811 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1810 } else if (var != NULL && !var->is_this() && var->is_global()) { |
1812 // Call to a global variable. | 1811 // Call to a global variable. |
1813 // Push global object as receiver for the call IC lookup. | 1812 // Push global object as receiver for the call IC lookup. |
1814 __ push(CodeGenerator::GlobalObject()); | 1813 __ push(CodeGenerator::GlobalObject()); |
1815 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 1814 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
1816 } else if (var != NULL && var->slot() != NULL && | 1815 } else if (var != NULL && var->AsSlot() != NULL && |
1817 var->slot()->type() == Slot::LOOKUP) { | 1816 var->AsSlot()->type() == Slot::LOOKUP) { |
1818 // Call to a lookup slot (dynamically introduced variable). | 1817 // Call to a lookup slot (dynamically introduced variable). |
1819 Label slow, done; | 1818 Label slow, done; |
1820 | 1819 |
1821 // Generate code for loading from variables potentially shadowed | 1820 // Generate code for loading from variables potentially shadowed |
1822 // by eval-introduced variables. | 1821 // by eval-introduced variables. |
1823 EmitDynamicLoadFromSlotFastCase(var->slot(), | 1822 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
1824 NOT_INSIDE_TYPEOF, | 1823 NOT_INSIDE_TYPEOF, |
1825 &slow, | 1824 &slow, |
1826 &done); | 1825 &done); |
1827 | 1826 |
1828 __ bind(&slow); | 1827 __ bind(&slow); |
1829 // Call the runtime to find the function to call (returned in rax) | 1828 // Call the runtime to find the function to call (returned in rax) |
1830 // and the object holding it (returned in rdx). | 1829 // and the object holding it (returned in rdx). |
1831 __ push(context_register()); | 1830 __ push(context_register()); |
1832 __ Push(var->name()); | 1831 __ Push(var->name()); |
1833 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1832 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
(...skipping 965 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2799 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 2798 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
2800 Property* prop = expr->expression()->AsProperty(); | 2799 Property* prop = expr->expression()->AsProperty(); |
2801 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 2800 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
2802 if (prop == NULL && var == NULL) { | 2801 if (prop == NULL && var == NULL) { |
2803 // Result of deleting non-property, non-variable reference is true. | 2802 // Result of deleting non-property, non-variable reference is true. |
2804 // The subexpression may have side effects. | 2803 // The subexpression may have side effects. |
2805 VisitForEffect(expr->expression()); | 2804 VisitForEffect(expr->expression()); |
2806 context()->Plug(true); | 2805 context()->Plug(true); |
2807 } else if (var != NULL && | 2806 } else if (var != NULL && |
2808 !var->is_global() && | 2807 !var->is_global() && |
2809 var->slot() != NULL && | 2808 var->AsSlot() != NULL && |
2810 var->slot()->type() != Slot::LOOKUP) { | 2809 var->AsSlot()->type() != Slot::LOOKUP) { |
2811 // Result of deleting non-global, non-dynamic variables is false. | 2810 // Result of deleting non-global, non-dynamic variables is false. |
2812 // The subexpression does not have side effects. | 2811 // The subexpression does not have side effects. |
2813 context()->Plug(false); | 2812 context()->Plug(false); |
2814 } else { | 2813 } else { |
2815 // Property or variable reference. Call the delete builtin with | 2814 // Property or variable reference. Call the delete builtin with |
2816 // object and property name as arguments. | 2815 // object and property name as arguments. |
2817 if (prop != NULL) { | 2816 if (prop != NULL) { |
2818 VisitForStackValue(prop->obj()); | 2817 VisitForStackValue(prop->obj()); |
2819 VisitForStackValue(prop->key()); | 2818 VisitForStackValue(prop->key()); |
2820 } else if (var->is_global()) { | 2819 } else if (var->is_global()) { |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3089 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 3088 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
3090 Comment cmnt(masm_, "Global variable"); | 3089 Comment cmnt(masm_, "Global variable"); |
3091 __ Move(rcx, proxy->name()); | 3090 __ Move(rcx, proxy->name()); |
3092 __ movq(rax, CodeGenerator::GlobalObject()); | 3091 __ movq(rax, CodeGenerator::GlobalObject()); |
3093 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 3092 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
3094 // Use a regular load, not a contextual load, to avoid a reference | 3093 // Use a regular load, not a contextual load, to avoid a reference |
3095 // error. | 3094 // error. |
3096 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3095 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3097 context()->Plug(rax); | 3096 context()->Plug(rax); |
3098 } else if (proxy != NULL && | 3097 } else if (proxy != NULL && |
3099 proxy->var()->slot() != NULL && | 3098 proxy->var()->AsSlot() != NULL && |
3100 proxy->var()->slot()->type() == Slot::LOOKUP) { | 3099 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { |
3101 Label done, slow; | 3100 Label done, slow; |
3102 | 3101 |
3103 // Generate code for loading from variables potentially shadowed | 3102 // Generate code for loading from variables potentially shadowed |
3104 // by eval-introduced variables. | 3103 // by eval-introduced variables. |
3105 Slot* slot = proxy->var()->slot(); | 3104 Slot* slot = proxy->var()->AsSlot(); |
3106 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); | 3105 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); |
3107 | 3106 |
3108 __ bind(&slow); | 3107 __ bind(&slow); |
3109 __ push(rsi); | 3108 __ push(rsi); |
3110 __ Push(proxy->name()); | 3109 __ Push(proxy->name()); |
3111 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 3110 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
3112 __ bind(&done); | 3111 __ bind(&done); |
3113 | 3112 |
3114 context()->Plug(rax); | 3113 context()->Plug(rax); |
3115 } else { | 3114 } else { |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3420 __ ret(0); | 3419 __ ret(0); |
3421 } | 3420 } |
3422 | 3421 |
3423 | 3422 |
3424 #undef __ | 3423 #undef __ |
3425 | 3424 |
3426 | 3425 |
3427 } } // namespace v8::internal | 3426 } } // namespace v8::internal |
3428 | 3427 |
3429 #endif // V8_TARGET_ARCH_X64 | 3428 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |