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 eax and esi. It replaces the context | 96 // Context is returned in both eax and esi. It replaces the context |
97 // passed to us. It's saved in the stack and kept live in esi. | 97 // passed to us. It's saved in the stack and kept live in esi. |
98 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); | 98 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); |
99 | 99 |
100 // Copy parameters into context if necessary. | 100 // Copy parameters into context if necessary. |
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 __ mov(eax, Operand(ebp, parameter_offset)); | 108 __ mov(eax, Operand(ebp, 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 __ mov(Operand(esi, context_offset), eax); | 111 __ mov(Operand(esi, context_offset), eax); |
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 esi. | 114 // clobbering esi. |
115 __ mov(ecx, esi); | 115 __ mov(ecx, esi); |
116 __ RecordWrite(ecx, context_offset, eax, ebx); | 116 __ RecordWrite(ecx, context_offset, eax, ebx); |
117 } | 117 } |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 Variable* arguments = scope()->arguments()->AsVariable(); | 121 Variable* arguments = scope()->arguments(); |
122 if (arguments != NULL) { | 122 if (arguments != NULL) { |
123 // Function uses arguments object. | 123 // Function uses arguments object. |
124 Comment cmnt(masm_, "[ Allocate arguments object"); | 124 Comment cmnt(masm_, "[ Allocate arguments object"); |
125 if (function_in_register) { | 125 if (function_in_register) { |
126 __ push(edi); | 126 __ push(edi); |
127 } else { | 127 } else { |
128 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 128 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
129 } | 129 } |
130 // Receiver is just before the parameters on the caller's stack. | 130 // Receiver is just before the parameters on the caller's stack. |
131 int offset = scope()->num_parameters() * kPointerSize; | 131 int offset = scope()->num_parameters() * kPointerSize; |
132 __ lea(edx, | 132 __ lea(edx, |
133 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); | 133 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); |
134 __ push(edx); | 134 __ push(edx); |
135 __ push(Immediate(Smi::FromInt(scope()->num_parameters()))); | 135 __ push(Immediate(Smi::FromInt(scope()->num_parameters()))); |
136 // Arguments to ArgumentsAccessStub: | 136 // Arguments to ArgumentsAccessStub: |
137 // function, receiver address, parameter count. | 137 // function, receiver address, parameter count. |
138 // The stub will rewrite receiver and parameter count if the previous | 138 // The stub will rewrite receiver and parameter count if the previous |
139 // stack frame was an arguments adapter frame. | 139 // stack frame was an arguments adapter frame. |
140 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | 140 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
141 __ CallStub(&stub); | 141 __ CallStub(&stub); |
142 __ mov(ecx, eax); // Duplicate result. | 142 __ mov(ecx, eax); // Duplicate result. |
143 Move(arguments->slot(), eax, ebx, edx); | 143 Move(arguments->AsSlot(), eax, ebx, edx); |
144 Slot* dot_arguments_slot = | 144 Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot(); |
145 scope()->arguments_shadow()->AsVariable()->slot(); | |
146 Move(dot_arguments_slot, ecx, ebx, edx); | 145 Move(dot_arguments_slot, ecx, ebx, edx); |
147 } | 146 } |
148 | 147 |
149 { Comment cmnt(masm_, "[ Declarations"); | 148 { Comment cmnt(masm_, "[ Declarations"); |
150 // For named function expressions, declare the function name as a | 149 // For named function expressions, declare the function name as a |
151 // constant. | 150 // constant. |
152 if (scope()->is_function_scope() && scope()->function() != NULL) { | 151 if (scope()->is_function_scope() && scope()->function() != NULL) { |
153 EmitDeclaration(scope()->function(), Variable::CONST, NULL); | 152 EmitDeclaration(scope()->function(), Variable::CONST, NULL); |
154 } | 153 } |
155 // Visit all the explicit declarations unless there is an illegal | 154 // Visit all the explicit declarations unless there is an illegal |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 __ RecordWrite(scratch1, offset, src, scratch2); | 508 __ RecordWrite(scratch1, offset, src, scratch2); |
510 } | 509 } |
511 } | 510 } |
512 | 511 |
513 | 512 |
514 void FullCodeGenerator::EmitDeclaration(Variable* variable, | 513 void FullCodeGenerator::EmitDeclaration(Variable* variable, |
515 Variable::Mode mode, | 514 Variable::Mode mode, |
516 FunctionLiteral* function) { | 515 FunctionLiteral* function) { |
517 Comment cmnt(masm_, "[ Declaration"); | 516 Comment cmnt(masm_, "[ Declaration"); |
518 ASSERT(variable != NULL); // Must have been resolved. | 517 ASSERT(variable != NULL); // Must have been resolved. |
519 Slot* slot = variable->slot(); | 518 Slot* slot = variable->AsSlot(); |
520 Property* prop = variable->AsProperty(); | 519 Property* prop = variable->AsProperty(); |
521 if (slot != NULL) { | 520 if (slot != NULL) { |
522 switch (slot->type()) { | 521 switch (slot->type()) { |
523 case Slot::PARAMETER: | 522 case Slot::PARAMETER: |
524 case Slot::LOCAL: | 523 case Slot::LOCAL: |
525 if (mode == Variable::CONST) { | 524 if (mode == Variable::CONST) { |
526 __ mov(Operand(ebp, SlotOffset(slot)), | 525 __ mov(Operand(ebp, SlotOffset(slot)), |
527 Immediate(Factory::the_hole_value())); | 526 Immediate(Factory::the_hole_value())); |
528 } else if (function != NULL) { | 527 } else if (function != NULL) { |
529 VisitForAccumulatorValue(function); | 528 VisitForAccumulatorValue(function); |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 Label* done) { | 993 Label* done) { |
995 // Generate fast-case code for variables that might be shadowed by | 994 // Generate fast-case code for variables that might be shadowed by |
996 // eval-introduced variables. Eval is used a lot without | 995 // eval-introduced variables. Eval is used a lot without |
997 // introducing variables. In those cases, we do not want to | 996 // introducing variables. In those cases, we do not want to |
998 // perform a runtime call for all variables in the scope | 997 // perform a runtime call for all variables in the scope |
999 // containing the eval. | 998 // containing the eval. |
1000 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 999 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
1001 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); | 1000 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); |
1002 __ jmp(done); | 1001 __ jmp(done); |
1003 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 1002 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
1004 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | 1003 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); |
1005 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | 1004 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); |
1006 if (potential_slot != NULL) { | 1005 if (potential_slot != NULL) { |
1007 // Generate fast case for locals that rewrite to slots. | 1006 // Generate fast case for locals that rewrite to slots. |
1008 __ mov(eax, | 1007 __ mov(eax, |
1009 ContextSlotOperandCheckExtensions(potential_slot, slow)); | 1008 ContextSlotOperandCheckExtensions(potential_slot, slow)); |
1010 if (potential_slot->var()->mode() == Variable::CONST) { | 1009 if (potential_slot->var()->mode() == Variable::CONST) { |
1011 __ cmp(eax, Factory::the_hole_value()); | 1010 __ cmp(eax, Factory::the_hole_value()); |
1012 __ j(not_equal, done); | 1011 __ j(not_equal, done); |
1013 __ mov(eax, Factory::undefined_value()); | 1012 __ mov(eax, Factory::undefined_value()); |
1014 } | 1013 } |
1015 __ jmp(done); | 1014 __ jmp(done); |
1016 } else if (rewrite != NULL) { | 1015 } else if (rewrite != NULL) { |
1017 // Generate fast case for calls of an argument function. | 1016 // Generate fast case for calls of an argument function. |
1018 Property* property = rewrite->AsProperty(); | 1017 Property* property = rewrite->AsProperty(); |
1019 if (property != NULL) { | 1018 if (property != NULL) { |
1020 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | 1019 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); |
1021 Literal* key_literal = property->key()->AsLiteral(); | 1020 Literal* key_literal = property->key()->AsLiteral(); |
1022 if (obj_proxy != NULL && | 1021 if (obj_proxy != NULL && |
1023 key_literal != NULL && | 1022 key_literal != NULL && |
1024 obj_proxy->IsArguments() && | 1023 obj_proxy->IsArguments() && |
1025 key_literal->handle()->IsSmi()) { | 1024 key_literal->handle()->IsSmi()) { |
1026 // Load arguments object if there are no eval-introduced | 1025 // Load arguments object if there are no eval-introduced |
1027 // variables. Then load the argument from the arguments | 1026 // variables. Then load the argument from the arguments |
1028 // object using keyed load. | 1027 // object using keyed load. |
1029 __ mov(edx, | 1028 __ mov(edx, |
1030 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | 1029 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
1031 slow)); | 1030 slow)); |
1032 __ mov(eax, Immediate(key_literal->handle())); | 1031 __ mov(eax, Immediate(key_literal->handle())); |
1033 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1032 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1034 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1033 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1035 __ jmp(done); | 1034 __ jmp(done); |
1036 } | 1035 } |
1037 } | 1036 } |
1038 } | 1037 } |
1039 } | 1038 } |
1040 } | 1039 } |
1041 | 1040 |
1042 | 1041 |
1043 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1042 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
1044 // Four cases: non-this global variables, lookup slots, all other | 1043 // Four cases: non-this global variables, lookup slots, all other |
1045 // types of slots, and parameters that rewrite to explicit property | 1044 // types of slots, and parameters that rewrite to explicit property |
1046 // accesses on the arguments object. | 1045 // accesses on the arguments object. |
1047 Slot* slot = var->slot(); | 1046 Slot* slot = var->AsSlot(); |
1048 Property* property = var->AsProperty(); | 1047 Property* property = var->AsProperty(); |
1049 | 1048 |
1050 if (var->is_global() && !var->is_this()) { | 1049 if (var->is_global() && !var->is_this()) { |
1051 Comment cmnt(masm_, "Global variable"); | 1050 Comment cmnt(masm_, "Global variable"); |
1052 // Use inline caching. Variable name is passed in ecx and the global | 1051 // Use inline caching. Variable name is passed in ecx and the global |
1053 // object on the stack. | 1052 // object on the stack. |
1054 __ mov(eax, CodeGenerator::GlobalObject()); | 1053 __ mov(eax, CodeGenerator::GlobalObject()); |
1055 __ mov(ecx, var->name()); | 1054 __ mov(ecx, var->name()); |
1056 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1055 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1057 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1056 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 } | 1092 } |
1094 | 1093 |
1095 } else { | 1094 } else { |
1096 Comment cmnt(masm_, "Rewritten parameter"); | 1095 Comment cmnt(masm_, "Rewritten parameter"); |
1097 ASSERT_NOT_NULL(property); | 1096 ASSERT_NOT_NULL(property); |
1098 // Rewritten parameter accesses are of the form "slot[literal]". | 1097 // Rewritten parameter accesses are of the form "slot[literal]". |
1099 | 1098 |
1100 // Assert that the object is in a slot. | 1099 // Assert that the object is in a slot. |
1101 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); | 1100 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); |
1102 ASSERT_NOT_NULL(object_var); | 1101 ASSERT_NOT_NULL(object_var); |
1103 Slot* object_slot = object_var->slot(); | 1102 Slot* object_slot = object_var->AsSlot(); |
1104 ASSERT_NOT_NULL(object_slot); | 1103 ASSERT_NOT_NULL(object_slot); |
1105 | 1104 |
1106 // Load the object. | 1105 // Load the object. |
1107 MemOperand object_loc = EmitSlotSearch(object_slot, eax); | 1106 MemOperand object_loc = EmitSlotSearch(object_slot, eax); |
1108 __ mov(edx, object_loc); | 1107 __ mov(edx, object_loc); |
1109 | 1108 |
1110 // Assert that the key is a smi. | 1109 // Assert that the key is a smi. |
1111 Literal* key_literal = property->key()->AsLiteral(); | 1110 Literal* key_literal = property->key()->AsLiteral(); |
1112 ASSERT_NOT_NULL(key_literal); | 1111 ASSERT_NOT_NULL(key_literal); |
1113 ASSERT(key_literal->handle()->IsSmi()); | 1112 ASSERT(key_literal->handle()->IsSmi()); |
(...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1802 } | 1801 } |
1803 } | 1802 } |
1804 } | 1803 } |
1805 | 1804 |
1806 | 1805 |
1807 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1806 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1808 Token::Value op) { | 1807 Token::Value op) { |
1809 // Left-hand sides that rewrite to explicit property accesses do not reach | 1808 // Left-hand sides that rewrite to explicit property accesses do not reach |
1810 // here. | 1809 // here. |
1811 ASSERT(var != NULL); | 1810 ASSERT(var != NULL); |
1812 ASSERT(var->is_global() || var->slot() != NULL); | 1811 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1813 | 1812 |
1814 if (var->is_global()) { | 1813 if (var->is_global()) { |
1815 ASSERT(!var->is_this()); | 1814 ASSERT(!var->is_this()); |
1816 // Assignment to a global variable. Use inline caching for the | 1815 // Assignment to a global variable. Use inline caching for the |
1817 // assignment. Right-hand-side value is passed in eax, variable name in | 1816 // assignment. Right-hand-side value is passed in eax, variable name in |
1818 // ecx, and the global object on the stack. | 1817 // ecx, and the global object on the stack. |
1819 __ mov(ecx, var->name()); | 1818 __ mov(ecx, var->name()); |
1820 __ mov(edx, CodeGenerator::GlobalObject()); | 1819 __ mov(edx, CodeGenerator::GlobalObject()); |
1821 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1820 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1822 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1821 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1823 | 1822 |
1824 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { | 1823 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { |
1825 // Perform the assignment for non-const variables and for initialization | 1824 // Perform the assignment for non-const variables and for initialization |
1826 // of const variables. Const assignments are simply skipped. | 1825 // of const variables. Const assignments are simply skipped. |
1827 Label done; | 1826 Label done; |
1828 Slot* slot = var->slot(); | 1827 Slot* slot = var->AsSlot(); |
1829 switch (slot->type()) { | 1828 switch (slot->type()) { |
1830 case Slot::PARAMETER: | 1829 case Slot::PARAMETER: |
1831 case Slot::LOCAL: | 1830 case Slot::LOCAL: |
1832 if (op == Token::INIT_CONST) { | 1831 if (op == Token::INIT_CONST) { |
1833 // Detect const reinitialization by checking for the hole value. | 1832 // Detect const reinitialization by checking for the hole value. |
1834 __ mov(edx, Operand(ebp, SlotOffset(slot))); | 1833 __ mov(edx, Operand(ebp, SlotOffset(slot))); |
1835 __ cmp(edx, Factory::the_hole_value()); | 1834 __ cmp(edx, Factory::the_hole_value()); |
1836 __ j(not_equal, &done); | 1835 __ j(not_equal, &done); |
1837 } | 1836 } |
1838 // Perform the assignment. | 1837 // Perform the assignment. |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2079 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2078 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2080 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 2079 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
2081 __ CallStub(&stub); | 2080 __ CallStub(&stub); |
2082 // Restore context register. | 2081 // Restore context register. |
2083 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2082 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2084 context()->DropAndPlug(1, eax); | 2083 context()->DropAndPlug(1, eax); |
2085 } else if (var != NULL && !var->is_this() && var->is_global()) { | 2084 } else if (var != NULL && !var->is_this() && var->is_global()) { |
2086 // Push global object as receiver for the call IC. | 2085 // Push global object as receiver for the call IC. |
2087 __ push(CodeGenerator::GlobalObject()); | 2086 __ push(CodeGenerator::GlobalObject()); |
2088 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2087 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
2089 } else if (var != NULL && var->slot() != NULL && | 2088 } else if (var != NULL && var->AsSlot() != NULL && |
2090 var->slot()->type() == Slot::LOOKUP) { | 2089 var->AsSlot()->type() == Slot::LOOKUP) { |
2091 // Call to a lookup slot (dynamically introduced variable). | 2090 // Call to a lookup slot (dynamically introduced variable). |
2092 Label slow, done; | 2091 Label slow, done; |
2093 | 2092 |
2094 // Generate code for loading from variables potentially shadowed | 2093 // Generate code for loading from variables potentially shadowed |
2095 // by eval-introduced variables. | 2094 // by eval-introduced variables. |
2096 EmitDynamicLoadFromSlotFastCase(var->slot(), | 2095 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
2097 NOT_INSIDE_TYPEOF, | 2096 NOT_INSIDE_TYPEOF, |
2098 &slow, | 2097 &slow, |
2099 &done); | 2098 &done); |
2100 | 2099 |
2101 __ bind(&slow); | 2100 __ bind(&slow); |
2102 // Call the runtime to find the function to call (returned in eax) | 2101 // Call the runtime to find the function to call (returned in eax) |
2103 // and the object holding it (returned in edx). | 2102 // and the object holding it (returned in edx). |
2104 __ push(context_register()); | 2103 __ push(context_register()); |
2105 __ push(Immediate(var->name())); | 2104 __ push(Immediate(var->name())); |
2106 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 2105 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
(...skipping 981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3088 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3087 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
3089 Property* prop = expr->expression()->AsProperty(); | 3088 Property* prop = expr->expression()->AsProperty(); |
3090 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 3089 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
3091 if (prop == NULL && var == NULL) { | 3090 if (prop == NULL && var == NULL) { |
3092 // Result of deleting non-property, non-variable reference is true. | 3091 // Result of deleting non-property, non-variable reference is true. |
3093 // The subexpression may have side effects. | 3092 // The subexpression may have side effects. |
3094 VisitForEffect(expr->expression()); | 3093 VisitForEffect(expr->expression()); |
3095 context()->Plug(true); | 3094 context()->Plug(true); |
3096 } else if (var != NULL && | 3095 } else if (var != NULL && |
3097 !var->is_global() && | 3096 !var->is_global() && |
3098 var->slot() != NULL && | 3097 var->AsSlot() != NULL && |
3099 var->slot()->type() != Slot::LOOKUP) { | 3098 var->AsSlot()->type() != Slot::LOOKUP) { |
3100 // Result of deleting non-global, non-dynamic variables is false. | 3099 // Result of deleting non-global, non-dynamic variables is false. |
3101 // The subexpression does not have side effects. | 3100 // The subexpression does not have side effects. |
3102 context()->Plug(false); | 3101 context()->Plug(false); |
3103 } else { | 3102 } else { |
3104 // Property or variable reference. Call the delete builtin with | 3103 // Property or variable reference. Call the delete builtin with |
3105 // object and property name as arguments. | 3104 // object and property name as arguments. |
3106 if (prop != NULL) { | 3105 if (prop != NULL) { |
3107 VisitForStackValue(prop->obj()); | 3106 VisitForStackValue(prop->obj()); |
3108 VisitForStackValue(prop->key()); | 3107 VisitForStackValue(prop->key()); |
3109 } else if (var->is_global()) { | 3108 } else if (var->is_global()) { |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3386 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 3385 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
3387 Comment cmnt(masm_, "Global variable"); | 3386 Comment cmnt(masm_, "Global variable"); |
3388 __ mov(eax, CodeGenerator::GlobalObject()); | 3387 __ mov(eax, CodeGenerator::GlobalObject()); |
3389 __ mov(ecx, Immediate(proxy->name())); | 3388 __ mov(ecx, Immediate(proxy->name())); |
3390 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 3389 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
3391 // Use a regular load, not a contextual load, to avoid a reference | 3390 // Use a regular load, not a contextual load, to avoid a reference |
3392 // error. | 3391 // error. |
3393 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3392 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3394 context()->Plug(eax); | 3393 context()->Plug(eax); |
3395 } else if (proxy != NULL && | 3394 } else if (proxy != NULL && |
3396 proxy->var()->slot() != NULL && | 3395 proxy->var()->AsSlot() != NULL && |
3397 proxy->var()->slot()->type() == Slot::LOOKUP) { | 3396 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { |
3398 Label done, slow; | 3397 Label done, slow; |
3399 | 3398 |
3400 // Generate code for loading from variables potentially shadowed | 3399 // Generate code for loading from variables potentially shadowed |
3401 // by eval-introduced variables. | 3400 // by eval-introduced variables. |
3402 Slot* slot = proxy->var()->slot(); | 3401 Slot* slot = proxy->var()->AsSlot(); |
3403 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); | 3402 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); |
3404 | 3403 |
3405 __ bind(&slow); | 3404 __ bind(&slow); |
3406 __ push(esi); | 3405 __ push(esi); |
3407 __ push(Immediate(proxy->name())); | 3406 __ push(Immediate(proxy->name())); |
3408 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 3407 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
3409 __ bind(&done); | 3408 __ bind(&done); |
3410 | 3409 |
3411 context()->Plug(eax); | 3410 context()->Plug(eax); |
3412 } else { | 3411 } else { |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3717 // And return. | 3716 // And return. |
3718 __ ret(0); | 3717 __ ret(0); |
3719 } | 3718 } |
3720 | 3719 |
3721 | 3720 |
3722 #undef __ | 3721 #undef __ |
3723 | 3722 |
3724 } } // namespace v8::internal | 3723 } } // namespace v8::internal |
3725 | 3724 |
3726 #endif // V8_TARGET_ARCH_IA32 | 3725 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |