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