| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
| 6 | 6 |
| 7 #include "src/full-codegen/full-codegen.h" | 7 #include "src/full-codegen/full-codegen.h" |
| 8 #include "src/ast/compile-time-value.h" | 8 #include "src/ast/compile-time-value.h" |
| 9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 if (variable->binding_needs_init()) { | 749 if (variable->binding_needs_init()) { |
| 750 Comment cmnt(masm_, "[ VariableDeclaration"); | 750 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 751 EmitDebugCheckDeclarationContext(variable); | 751 EmitDebugCheckDeclarationContext(variable); |
| 752 __ mov(ContextOperand(esi, variable->index()), | 752 __ mov(ContextOperand(esi, variable->index()), |
| 753 Immediate(isolate()->factory()->the_hole_value())); | 753 Immediate(isolate()->factory()->the_hole_value())); |
| 754 // No write barrier since the hole value is in old space. | 754 // No write barrier since the hole value is in old space. |
| 755 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 755 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 756 } | 756 } |
| 757 break; | 757 break; |
| 758 | 758 |
| 759 case VariableLocation::LOOKUP: { | 759 case VariableLocation::LOOKUP: |
| 760 Comment cmnt(masm_, "[ VariableDeclaration"); | |
| 761 DCHECK_EQ(VAR, variable->mode()); | |
| 762 DCHECK(!variable->binding_needs_init()); | |
| 763 __ push(Immediate(variable->name())); | |
| 764 __ CallRuntime(Runtime::kDeclareEvalVar); | |
| 765 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | |
| 766 break; | |
| 767 } | |
| 768 | |
| 769 case VariableLocation::MODULE: | 760 case VariableLocation::MODULE: |
| 770 UNREACHABLE(); | 761 UNREACHABLE(); |
| 771 } | 762 } |
| 772 } | 763 } |
| 773 | 764 |
| 774 | 765 |
| 775 void FullCodeGenerator::VisitFunctionDeclaration( | 766 void FullCodeGenerator::VisitFunctionDeclaration( |
| 776 FunctionDeclaration* declaration) { | 767 FunctionDeclaration* declaration) { |
| 777 VariableProxy* proxy = declaration->proxy(); | 768 VariableProxy* proxy = declaration->proxy(); |
| 778 Variable* variable = proxy->var(); | 769 Variable* variable = proxy->var(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 808 Context::SlotOffset(variable->index()), | 799 Context::SlotOffset(variable->index()), |
| 809 result_register(), | 800 result_register(), |
| 810 ecx, | 801 ecx, |
| 811 kDontSaveFPRegs, | 802 kDontSaveFPRegs, |
| 812 EMIT_REMEMBERED_SET, | 803 EMIT_REMEMBERED_SET, |
| 813 OMIT_SMI_CHECK); | 804 OMIT_SMI_CHECK); |
| 814 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 805 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 815 break; | 806 break; |
| 816 } | 807 } |
| 817 | 808 |
| 818 case VariableLocation::LOOKUP: { | 809 case VariableLocation::LOOKUP: |
| 819 Comment cmnt(masm_, "[ FunctionDeclaration"); | |
| 820 PushOperand(variable->name()); | |
| 821 VisitForStackValue(declaration->fun()); | |
| 822 CallRuntimeWithOperands(Runtime::kDeclareEvalFunction); | |
| 823 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | |
| 824 break; | |
| 825 } | |
| 826 | |
| 827 case VariableLocation::MODULE: | 810 case VariableLocation::MODULE: |
| 828 UNREACHABLE(); | 811 UNREACHABLE(); |
| 829 } | 812 } |
| 830 } | 813 } |
| 831 | 814 |
| 832 | 815 |
| 833 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 816 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 834 // Call the runtime to declare the globals. | 817 // Call the runtime to declare the globals. |
| 835 __ Push(pairs); | 818 __ Push(pairs); |
| 836 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 819 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1102 | 1085 |
| 1103 void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, | 1086 void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, |
| 1104 int offset, | 1087 int offset, |
| 1105 FeedbackVectorSlot slot) { | 1088 FeedbackVectorSlot slot) { |
| 1106 DCHECK(NeedsHomeObject(initializer)); | 1089 DCHECK(NeedsHomeObject(initializer)); |
| 1107 __ mov(StoreDescriptor::ReceiverRegister(), eax); | 1090 __ mov(StoreDescriptor::ReceiverRegister(), eax); |
| 1108 __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize)); | 1091 __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize)); |
| 1109 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); | 1092 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); |
| 1110 } | 1093 } |
| 1111 | 1094 |
| 1112 | |
| 1113 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, | |
| 1114 TypeofMode typeof_mode, | |
| 1115 Label* slow) { | |
| 1116 Register context = esi; | |
| 1117 Register temp = edx; | |
| 1118 | |
| 1119 int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval(); | |
| 1120 for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) { | |
| 1121 if (!s->NeedsContext()) continue; | |
| 1122 if (s->calls_sloppy_eval()) { | |
| 1123 // Check that extension is "the hole". | |
| 1124 __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX), | |
| 1125 Heap::kTheHoleValueRootIndex, slow); | |
| 1126 } | |
| 1127 // Load next context in chain. | |
| 1128 __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | |
| 1129 // Walk the rest of the chain without clobbering esi. | |
| 1130 context = temp; | |
| 1131 to_check--; | |
| 1132 } | |
| 1133 | |
| 1134 // All extension objects were empty and it is safe to use a normal global | |
| 1135 // load machinery. | |
| 1136 EmitGlobalVariableLoad(proxy, typeof_mode); | |
| 1137 } | |
| 1138 | |
| 1139 | |
| 1140 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | |
| 1141 Label* slow) { | |
| 1142 DCHECK(var->IsContextSlot()); | |
| 1143 Register context = esi; | |
| 1144 Register temp = ebx; | |
| 1145 | |
| 1146 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | |
| 1147 if (s->NeedsContext()) { | |
| 1148 if (s->calls_sloppy_eval()) { | |
| 1149 // Check that extension is "the hole". | |
| 1150 __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX), | |
| 1151 Heap::kTheHoleValueRootIndex, slow); | |
| 1152 } | |
| 1153 __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | |
| 1154 // Walk the rest of the chain without clobbering esi. | |
| 1155 context = temp; | |
| 1156 } | |
| 1157 } | |
| 1158 // Check that last extension is "the hole". | |
| 1159 __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX), | |
| 1160 Heap::kTheHoleValueRootIndex, slow); | |
| 1161 | |
| 1162 // This function is used only for loads, not stores, so it's safe to | |
| 1163 // return an esi-based operand (the write barrier cannot be allowed to | |
| 1164 // destroy the esi register). | |
| 1165 return ContextOperand(context, var->index()); | |
| 1166 } | |
| 1167 | |
| 1168 | |
| 1169 void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, | |
| 1170 TypeofMode typeof_mode, | |
| 1171 Label* slow, Label* done) { | |
| 1172 // Generate fast-case code for variables that might be shadowed by | |
| 1173 // eval-introduced variables. Eval is used a lot without | |
| 1174 // introducing variables. In those cases, we do not want to | |
| 1175 // perform a runtime call for all variables in the scope | |
| 1176 // containing the eval. | |
| 1177 Variable* var = proxy->var(); | |
| 1178 if (var->mode() == DYNAMIC_GLOBAL) { | |
| 1179 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); | |
| 1180 __ jmp(done); | |
| 1181 } else if (var->mode() == DYNAMIC_LOCAL) { | |
| 1182 Variable* local = var->local_if_not_shadowed(); | |
| 1183 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); | |
| 1184 if (local->binding_needs_init()) { | |
| 1185 __ cmp(eax, isolate()->factory()->the_hole_value()); | |
| 1186 __ j(not_equal, done); | |
| 1187 __ push(Immediate(var->name())); | |
| 1188 __ CallRuntime(Runtime::kThrowReferenceError); | |
| 1189 } else { | |
| 1190 __ jmp(done); | |
| 1191 } | |
| 1192 } | |
| 1193 } | |
| 1194 | |
| 1195 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1095 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
| 1196 TypeofMode typeof_mode) { | 1096 TypeofMode typeof_mode) { |
| 1197 SetExpressionPosition(proxy); | 1097 SetExpressionPosition(proxy); |
| 1198 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 1098 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); |
| 1199 Variable* var = proxy->var(); | 1099 Variable* var = proxy->var(); |
| 1200 | 1100 |
| 1201 // Three cases: global variables, lookup variables, and all other types of | 1101 // Two cases: global variables and all other types of variables. |
| 1202 // variables. | |
| 1203 switch (var->location()) { | 1102 switch (var->location()) { |
| 1204 case VariableLocation::UNALLOCATED: { | 1103 case VariableLocation::UNALLOCATED: { |
| 1205 Comment cmnt(masm_, "[ Global variable"); | 1104 Comment cmnt(masm_, "[ Global variable"); |
| 1206 EmitGlobalVariableLoad(proxy, typeof_mode); | 1105 EmitGlobalVariableLoad(proxy, typeof_mode); |
| 1207 context()->Plug(eax); | 1106 context()->Plug(eax); |
| 1208 break; | 1107 break; |
| 1209 } | 1108 } |
| 1210 | 1109 |
| 1211 case VariableLocation::PARAMETER: | 1110 case VariableLocation::PARAMETER: |
| 1212 case VariableLocation::LOCAL: | 1111 case VariableLocation::LOCAL: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1225 __ push(Immediate(var->name())); | 1124 __ push(Immediate(var->name())); |
| 1226 __ CallRuntime(Runtime::kThrowReferenceError); | 1125 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1227 __ bind(&done); | 1126 __ bind(&done); |
| 1228 context()->Plug(eax); | 1127 context()->Plug(eax); |
| 1229 break; | 1128 break; |
| 1230 } | 1129 } |
| 1231 context()->Plug(var); | 1130 context()->Plug(var); |
| 1232 break; | 1131 break; |
| 1233 } | 1132 } |
| 1234 | 1133 |
| 1235 case VariableLocation::LOOKUP: { | 1134 case VariableLocation::LOOKUP: |
| 1236 Comment cmnt(masm_, "[ Lookup variable"); | |
| 1237 Label done, slow; | |
| 1238 // Generate code for loading from variables potentially shadowed | |
| 1239 // by eval-introduced variables. | |
| 1240 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | |
| 1241 __ bind(&slow); | |
| 1242 __ push(Immediate(var->name())); | |
| 1243 Runtime::FunctionId function_id = | |
| 1244 typeof_mode == NOT_INSIDE_TYPEOF | |
| 1245 ? Runtime::kLoadLookupSlot | |
| 1246 : Runtime::kLoadLookupSlotInsideTypeof; | |
| 1247 __ CallRuntime(function_id); | |
| 1248 __ bind(&done); | |
| 1249 context()->Plug(eax); | |
| 1250 break; | |
| 1251 } | |
| 1252 | |
| 1253 case VariableLocation::MODULE: | 1135 case VariableLocation::MODULE: |
| 1254 UNREACHABLE(); | 1136 UNREACHABLE(); |
| 1255 } | 1137 } |
| 1256 } | 1138 } |
| 1257 | 1139 |
| 1258 | 1140 |
| 1259 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { | 1141 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { |
| 1260 Expression* expression = (property == NULL) ? NULL : property->value(); | 1142 Expression* expression = (property == NULL) ? NULL : property->value(); |
| 1261 if (expression == NULL) { | 1143 if (expression == NULL) { |
| 1262 PushOperand(isolate()->factory()->null_value()); | 1144 PushOperand(isolate()->factory()->null_value()); |
| (...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2000 __ mov(edx, location); | 1882 __ mov(edx, location); |
| 2001 __ cmp(edx, isolate()->factory()->the_hole_value()); | 1883 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2002 __ j(equal, &uninitialized_this); | 1884 __ j(equal, &uninitialized_this); |
| 2003 __ push(Immediate(var->name())); | 1885 __ push(Immediate(var->name())); |
| 2004 __ CallRuntime(Runtime::kThrowReferenceError); | 1886 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2005 __ bind(&uninitialized_this); | 1887 __ bind(&uninitialized_this); |
| 2006 EmitStoreToStackLocalOrContextSlot(var, location); | 1888 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2007 | 1889 |
| 2008 } else { | 1890 } else { |
| 2009 DCHECK(var->mode() != CONST || op == Token::INIT); | 1891 DCHECK(var->mode() != CONST || op == Token::INIT); |
| 2010 if (var->IsLookupSlot()) { | 1892 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2011 // Assignment to var. | 1893 DCHECK(!var->IsLookupSlot()); |
| 2012 __ Push(Immediate(var->name())); | 1894 // Assignment to var or initializing assignment to let/const in harmony |
| 2013 __ Push(eax); | 1895 // mode. |
| 2014 __ CallRuntime(is_strict(language_mode()) | 1896 MemOperand location = VarOperand(var, ecx); |
| 2015 ? Runtime::kStoreLookupSlot_Strict | 1897 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
| 2016 : Runtime::kStoreLookupSlot_Sloppy); | 1898 // Check for an uninitialized let binding. |
| 2017 } else { | 1899 __ mov(edx, location); |
| 2018 // Assignment to var or initializing assignment to let/const in harmony | 1900 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2019 // mode. | 1901 __ Check(equal, kLetBindingReInitialization); |
| 2020 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | |
| 2021 MemOperand location = VarOperand(var, ecx); | |
| 2022 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | |
| 2023 // Check for an uninitialized let binding. | |
| 2024 __ mov(edx, location); | |
| 2025 __ cmp(edx, isolate()->factory()->the_hole_value()); | |
| 2026 __ Check(equal, kLetBindingReInitialization); | |
| 2027 } | |
| 2028 EmitStoreToStackLocalOrContextSlot(var, location); | |
| 2029 } | 1902 } |
| 1903 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2030 } | 1904 } |
| 2031 } | 1905 } |
| 2032 | 1906 |
| 2033 | 1907 |
| 2034 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1908 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2035 // Assignment to a property, using a named store IC. | 1909 // Assignment to a property, using a named store IC. |
| 2036 // eax : value | 1910 // eax : value |
| 2037 // esp[0] : receiver | 1911 // esp[0] : receiver |
| 2038 Property* prop = expr->target()->AsProperty(); | 1912 Property* prop = expr->target()->AsProperty(); |
| 2039 DCHECK(prop != NULL); | 1913 DCHECK(prop != NULL); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2239 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2113 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 2240 __ Move(eax, Immediate(arg_count)); | 2114 __ Move(eax, Immediate(arg_count)); |
| 2241 CallIC(code); | 2115 CallIC(code); |
| 2242 OperandStackDepthDecrement(arg_count + 1); | 2116 OperandStackDepthDecrement(arg_count + 1); |
| 2243 | 2117 |
| 2244 RecordJSReturnSite(expr); | 2118 RecordJSReturnSite(expr); |
| 2245 RestoreContext(); | 2119 RestoreContext(); |
| 2246 context()->DropAndPlug(1, eax); | 2120 context()->DropAndPlug(1, eax); |
| 2247 } | 2121 } |
| 2248 | 2122 |
| 2249 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { | |
| 2250 int arg_count = expr->arguments()->length(); | |
| 2251 // Push copy of the first argument or undefined if it doesn't exist. | |
| 2252 if (arg_count > 0) { | |
| 2253 __ push(Operand(esp, arg_count * kPointerSize)); | |
| 2254 } else { | |
| 2255 __ push(Immediate(isolate()->factory()->undefined_value())); | |
| 2256 } | |
| 2257 | |
| 2258 // Push the enclosing function. | |
| 2259 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | |
| 2260 | |
| 2261 // Push the language mode. | |
| 2262 __ push(Immediate(Smi::FromInt(language_mode()))); | |
| 2263 | |
| 2264 // Push the start position of the scope the calls resides in. | |
| 2265 __ push(Immediate(Smi::FromInt(scope()->start_position()))); | |
| 2266 | |
| 2267 // Push the source position of the eval call. | |
| 2268 __ push(Immediate(Smi::FromInt(expr->position()))); | |
| 2269 | |
| 2270 // Do the runtime call. | |
| 2271 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); | |
| 2272 } | |
| 2273 | |
| 2274 | |
| 2275 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | |
| 2276 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | |
| 2277 VariableProxy* callee = expr->expression()->AsVariableProxy(); | |
| 2278 if (callee->var()->IsLookupSlot()) { | |
| 2279 Label slow, done; | |
| 2280 SetExpressionPosition(callee); | |
| 2281 // Generate code for loading from variables potentially shadowed by | |
| 2282 // eval-introduced variables. | |
| 2283 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | |
| 2284 | |
| 2285 __ bind(&slow); | |
| 2286 // Call the runtime to find the function to call (returned in eax) and | |
| 2287 // the object holding it (returned in edx). | |
| 2288 __ Push(callee->name()); | |
| 2289 __ CallRuntime(Runtime::kLoadLookupSlotForCall); | |
| 2290 PushOperand(eax); // Function. | |
| 2291 PushOperand(edx); // Receiver. | |
| 2292 PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS); | |
| 2293 | |
| 2294 // If fast case code has been generated, emit code to push the function | |
| 2295 // and receiver and have the slow path jump around this code. | |
| 2296 if (done.is_linked()) { | |
| 2297 Label call; | |
| 2298 __ jmp(&call, Label::kNear); | |
| 2299 __ bind(&done); | |
| 2300 // Push function. | |
| 2301 __ push(eax); | |
| 2302 // The receiver is implicitly the global receiver. Indicate this by | |
| 2303 // passing the hole to the call function stub. | |
| 2304 __ push(Immediate(isolate()->factory()->undefined_value())); | |
| 2305 __ bind(&call); | |
| 2306 } | |
| 2307 } else { | |
| 2308 VisitForStackValue(callee); | |
| 2309 // refEnv.WithBaseObject() | |
| 2310 PushOperand(isolate()->factory()->undefined_value()); | |
| 2311 } | |
| 2312 } | |
| 2313 | |
| 2314 | |
| 2315 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) { | |
| 2316 // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval | |
| 2317 // to resolve the function we need to call. Then we call the resolved | |
| 2318 // function using the given arguments. | |
| 2319 ZoneList<Expression*>* args = expr->arguments(); | |
| 2320 int arg_count = args->length(); | |
| 2321 | |
| 2322 PushCalleeAndWithBaseObject(expr); | |
| 2323 | |
| 2324 // Push the arguments. | |
| 2325 for (int i = 0; i < arg_count; i++) { | |
| 2326 VisitForStackValue(args->at(i)); | |
| 2327 } | |
| 2328 | |
| 2329 // Push a copy of the function (found below the arguments) and | |
| 2330 // resolve eval. | |
| 2331 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); | |
| 2332 EmitResolvePossiblyDirectEval(expr); | |
| 2333 | |
| 2334 // Touch up the stack with the resolved function. | |
| 2335 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); | |
| 2336 | |
| 2337 PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS); | |
| 2338 | |
| 2339 SetCallPosition(expr); | |
| 2340 Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny, | |
| 2341 expr->tail_call_mode()) | |
| 2342 .code(); | |
| 2343 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); | |
| 2344 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | |
| 2345 __ Move(eax, Immediate(arg_count)); | |
| 2346 __ call(code, RelocInfo::CODE_TARGET); | |
| 2347 OperandStackDepthDecrement(arg_count + 1); | |
| 2348 RecordJSReturnSite(expr); | |
| 2349 RestoreContext(); | |
| 2350 context()->DropAndPlug(1, eax); | |
| 2351 } | |
| 2352 | |
| 2353 | |
| 2354 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2123 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
| 2355 Comment cmnt(masm_, "[ CallNew"); | 2124 Comment cmnt(masm_, "[ CallNew"); |
| 2356 // According to ECMA-262, section 11.2.2, page 44, the function | 2125 // According to ECMA-262, section 11.2.2, page 44, the function |
| 2357 // expression in new calls must be evaluated before the | 2126 // expression in new calls must be evaluated before the |
| 2358 // arguments. | 2127 // arguments. |
| 2359 | 2128 |
| 2360 // Push constructor on the stack. If it's not a function it's used as | 2129 // Push constructor on the stack. If it's not a function it's used as |
| 2361 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is | 2130 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is |
| 2362 // ignored. | 2131 // ignored. |
| 2363 DCHECK(!expr->expression()->IsSuperPropertyReference()); | 2132 DCHECK(!expr->expression()->IsSuperPropertyReference()); |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2767 // Delete of an unqualified identifier is disallowed in strict mode but | 2536 // Delete of an unqualified identifier is disallowed in strict mode but |
| 2768 // "delete this" is allowed. | 2537 // "delete this" is allowed. |
| 2769 bool is_this = var->is_this(); | 2538 bool is_this = var->is_this(); |
| 2770 DCHECK(is_sloppy(language_mode()) || is_this); | 2539 DCHECK(is_sloppy(language_mode()) || is_this); |
| 2771 if (var->IsUnallocated()) { | 2540 if (var->IsUnallocated()) { |
| 2772 __ mov(eax, NativeContextOperand()); | 2541 __ mov(eax, NativeContextOperand()); |
| 2773 __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); | 2542 __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); |
| 2774 __ push(Immediate(var->name())); | 2543 __ push(Immediate(var->name())); |
| 2775 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); | 2544 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
| 2776 context()->Plug(eax); | 2545 context()->Plug(eax); |
| 2777 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 2546 } else { |
| 2547 DCHECK(!var->IsLookupSlot()); |
| 2548 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2778 // Result of deleting non-global variables is false. 'this' is | 2549 // Result of deleting non-global variables is false. 'this' is |
| 2779 // not really a variable, though we implement it as one. The | 2550 // not really a variable, though we implement it as one. The |
| 2780 // subexpression does not have side effects. | 2551 // subexpression does not have side effects. |
| 2781 context()->Plug(is_this); | 2552 context()->Plug(is_this); |
| 2782 } else { | |
| 2783 // Non-global variable. Call the runtime to try to delete from the | |
| 2784 // context where the variable was introduced. | |
| 2785 __ Push(var->name()); | |
| 2786 __ CallRuntime(Runtime::kDeleteLookupSlot); | |
| 2787 context()->Plug(eax); | |
| 2788 } | 2553 } |
| 2789 } else { | 2554 } else { |
| 2790 // Result of deleting non-property, non-variable reference is true. | 2555 // Result of deleting non-property, non-variable reference is true. |
| 2791 // The subexpression may have side effects. | 2556 // The subexpression may have side effects. |
| 2792 VisitForEffect(expr->expression()); | 2557 VisitForEffect(expr->expression()); |
| 2793 context()->Plug(true); | 2558 context()->Plug(true); |
| 2794 } | 2559 } |
| 2795 break; | 2560 break; |
| 2796 } | 2561 } |
| 2797 | 2562 |
| (...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3477 isolate->builtins()->OnStackReplacement()->entry(), | 3242 isolate->builtins()->OnStackReplacement()->entry(), |
| 3478 Assembler::target_address_at(call_target_address, unoptimized_code)); | 3243 Assembler::target_address_at(call_target_address, unoptimized_code)); |
| 3479 return ON_STACK_REPLACEMENT; | 3244 return ON_STACK_REPLACEMENT; |
| 3480 } | 3245 } |
| 3481 | 3246 |
| 3482 | 3247 |
| 3483 } // namespace internal | 3248 } // namespace internal |
| 3484 } // namespace v8 | 3249 } // namespace v8 |
| 3485 | 3250 |
| 3486 #endif // V8_TARGET_ARCH_IA32 | 3251 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |