| 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_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
| 6 | 6 |
| 7 // Note on Mips implementation: | 7 // Note on Mips implementation: |
| 8 // | 8 // |
| 9 // The result_register() for mips is the 'v0' register, which is defined | 9 // The result_register() for mips is the 'v0' register, which is defined |
| 10 // by the ABI to contain function return values. However, the first | 10 // by the ABI to contain function return values. However, the first |
| (...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 if (variable->binding_needs_init()) { | 800 if (variable->binding_needs_init()) { |
| 801 Comment cmnt(masm_, "[ VariableDeclaration"); | 801 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 802 EmitDebugCheckDeclarationContext(variable); | 802 EmitDebugCheckDeclarationContext(variable); |
| 803 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 803 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 804 __ sw(at, ContextMemOperand(cp, variable->index())); | 804 __ sw(at, ContextMemOperand(cp, variable->index())); |
| 805 // No write barrier since the_hole_value is in old space. | 805 // No write barrier since the_hole_value is in old space. |
| 806 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 806 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 807 } | 807 } |
| 808 break; | 808 break; |
| 809 | 809 |
| 810 case VariableLocation::LOOKUP: { | 810 case VariableLocation::LOOKUP: |
| 811 Comment cmnt(masm_, "[ VariableDeclaration"); | |
| 812 DCHECK_EQ(VAR, variable->mode()); | |
| 813 DCHECK(!variable->binding_needs_init()); | |
| 814 __ li(a2, Operand(variable->name())); | |
| 815 __ Push(a2); | |
| 816 __ CallRuntime(Runtime::kDeclareEvalVar); | |
| 817 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | |
| 818 break; | |
| 819 } | |
| 820 | |
| 821 case VariableLocation::MODULE: | 811 case VariableLocation::MODULE: |
| 822 UNREACHABLE(); | 812 UNREACHABLE(); |
| 823 } | 813 } |
| 824 } | 814 } |
| 825 | 815 |
| 826 | 816 |
| 827 void FullCodeGenerator::VisitFunctionDeclaration( | 817 void FullCodeGenerator::VisitFunctionDeclaration( |
| 828 FunctionDeclaration* declaration) { | 818 FunctionDeclaration* declaration) { |
| 829 VariableProxy* proxy = declaration->proxy(); | 819 VariableProxy* proxy = declaration->proxy(); |
| 830 Variable* variable = proxy->var(); | 820 Variable* variable = proxy->var(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 result_register(), | 852 result_register(), |
| 863 a2, | 853 a2, |
| 864 kRAHasBeenSaved, | 854 kRAHasBeenSaved, |
| 865 kDontSaveFPRegs, | 855 kDontSaveFPRegs, |
| 866 EMIT_REMEMBERED_SET, | 856 EMIT_REMEMBERED_SET, |
| 867 OMIT_SMI_CHECK); | 857 OMIT_SMI_CHECK); |
| 868 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 858 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 869 break; | 859 break; |
| 870 } | 860 } |
| 871 | 861 |
| 872 case VariableLocation::LOOKUP: { | 862 case VariableLocation::LOOKUP: |
| 873 Comment cmnt(masm_, "[ FunctionDeclaration"); | |
| 874 __ li(a2, Operand(variable->name())); | |
| 875 PushOperand(a2); | |
| 876 // Push initial value for function declaration. | |
| 877 VisitForStackValue(declaration->fun()); | |
| 878 CallRuntimeWithOperands(Runtime::kDeclareEvalFunction); | |
| 879 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | |
| 880 break; | |
| 881 } | |
| 882 | |
| 883 case VariableLocation::MODULE: | 863 case VariableLocation::MODULE: |
| 884 UNREACHABLE(); | 864 UNREACHABLE(); |
| 885 } | 865 } |
| 886 } | 866 } |
| 887 | 867 |
| 888 | 868 |
| 889 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 869 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 890 // Call the runtime to declare the globals. | 870 // Call the runtime to declare the globals. |
| 891 __ li(a1, Operand(pairs)); | 871 __ li(a1, Operand(pairs)); |
| 892 __ li(a0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); | 872 __ li(a0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1176 void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, | 1156 void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, |
| 1177 int offset, | 1157 int offset, |
| 1178 FeedbackVectorSlot slot) { | 1158 FeedbackVectorSlot slot) { |
| 1179 DCHECK(NeedsHomeObject(initializer)); | 1159 DCHECK(NeedsHomeObject(initializer)); |
| 1180 __ Move(StoreDescriptor::ReceiverRegister(), v0); | 1160 __ Move(StoreDescriptor::ReceiverRegister(), v0); |
| 1181 __ lw(StoreDescriptor::ValueRegister(), | 1161 __ lw(StoreDescriptor::ValueRegister(), |
| 1182 MemOperand(sp, offset * kPointerSize)); | 1162 MemOperand(sp, offset * kPointerSize)); |
| 1183 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); | 1163 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); |
| 1184 } | 1164 } |
| 1185 | 1165 |
| 1186 | |
| 1187 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, | |
| 1188 TypeofMode typeof_mode, | |
| 1189 Label* slow) { | |
| 1190 Register current = cp; | |
| 1191 Register next = a1; | |
| 1192 Register temp = a2; | |
| 1193 | |
| 1194 int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval(); | |
| 1195 for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) { | |
| 1196 if (!s->NeedsContext()) continue; | |
| 1197 if (s->calls_sloppy_eval()) { | |
| 1198 // Check that extension is "the hole". | |
| 1199 __ lw(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); | |
| 1200 __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); | |
| 1201 } | |
| 1202 // Load next context in chain. | |
| 1203 __ lw(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); | |
| 1204 // Walk the rest of the chain without clobbering cp. | |
| 1205 current = next; | |
| 1206 to_check--; | |
| 1207 } | |
| 1208 | |
| 1209 // All extension objects were empty and it is safe to use a normal global | |
| 1210 // load machinery. | |
| 1211 EmitGlobalVariableLoad(proxy, typeof_mode); | |
| 1212 } | |
| 1213 | |
| 1214 | |
| 1215 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | |
| 1216 Label* slow) { | |
| 1217 DCHECK(var->IsContextSlot()); | |
| 1218 Register context = cp; | |
| 1219 Register next = a3; | |
| 1220 Register temp = t0; | |
| 1221 | |
| 1222 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | |
| 1223 if (s->NeedsContext()) { | |
| 1224 if (s->calls_sloppy_eval()) { | |
| 1225 // Check that extension is "the hole". | |
| 1226 __ lw(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); | |
| 1227 __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); | |
| 1228 } | |
| 1229 __ lw(next, ContextMemOperand(context, Context::PREVIOUS_INDEX)); | |
| 1230 // Walk the rest of the chain without clobbering cp. | |
| 1231 context = next; | |
| 1232 } | |
| 1233 } | |
| 1234 // Check that last extension is "the hole". | |
| 1235 __ lw(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); | |
| 1236 __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); | |
| 1237 | |
| 1238 // This function is used only for loads, not stores, so it's safe to | |
| 1239 // return an cp-based operand (the write barrier cannot be allowed to | |
| 1240 // destroy the cp register). | |
| 1241 return ContextMemOperand(context, var->index()); | |
| 1242 } | |
| 1243 | |
| 1244 | |
| 1245 void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, | |
| 1246 TypeofMode typeof_mode, | |
| 1247 Label* slow, Label* done) { | |
| 1248 // Generate fast-case code for variables that might be shadowed by | |
| 1249 // eval-introduced variables. Eval is used a lot without | |
| 1250 // introducing variables. In those cases, we do not want to | |
| 1251 // perform a runtime call for all variables in the scope | |
| 1252 // containing the eval. | |
| 1253 Variable* var = proxy->var(); | |
| 1254 if (var->mode() == DYNAMIC_GLOBAL) { | |
| 1255 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); | |
| 1256 __ Branch(done); | |
| 1257 } else if (var->mode() == DYNAMIC_LOCAL) { | |
| 1258 Variable* local = var->local_if_not_shadowed(); | |
| 1259 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); | |
| 1260 if (local->binding_needs_init()) { | |
| 1261 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | |
| 1262 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. | |
| 1263 __ Branch(done, ne, at, Operand(zero_reg)); | |
| 1264 __ li(a0, Operand(var->name())); | |
| 1265 __ push(a0); | |
| 1266 __ CallRuntime(Runtime::kThrowReferenceError); | |
| 1267 } else { | |
| 1268 __ Branch(done); | |
| 1269 } | |
| 1270 } | |
| 1271 } | |
| 1272 | |
| 1273 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1166 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
| 1274 TypeofMode typeof_mode) { | 1167 TypeofMode typeof_mode) { |
| 1275 // Record position before possible IC call. | 1168 // Record position before possible IC call. |
| 1276 SetExpressionPosition(proxy); | 1169 SetExpressionPosition(proxy); |
| 1277 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 1170 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); |
| 1278 Variable* var = proxy->var(); | 1171 Variable* var = proxy->var(); |
| 1279 | 1172 |
| 1280 // Three cases: global variables, lookup variables, and all other types of | 1173 // Two cases: global variables and all other types of variables. |
| 1281 // variables. | |
| 1282 switch (var->location()) { | 1174 switch (var->location()) { |
| 1283 case VariableLocation::UNALLOCATED: { | 1175 case VariableLocation::UNALLOCATED: { |
| 1284 Comment cmnt(masm_, "[ Global variable"); | 1176 Comment cmnt(masm_, "[ Global variable"); |
| 1285 EmitGlobalVariableLoad(proxy, typeof_mode); | 1177 EmitGlobalVariableLoad(proxy, typeof_mode); |
| 1286 context()->Plug(v0); | 1178 context()->Plug(v0); |
| 1287 break; | 1179 break; |
| 1288 } | 1180 } |
| 1289 | 1181 |
| 1290 case VariableLocation::PARAMETER: | 1182 case VariableLocation::PARAMETER: |
| 1291 case VariableLocation::LOCAL: | 1183 case VariableLocation::LOCAL: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1305 __ push(a0); | 1197 __ push(a0); |
| 1306 __ CallRuntime(Runtime::kThrowReferenceError); | 1198 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1307 __ bind(&done); | 1199 __ bind(&done); |
| 1308 context()->Plug(v0); | 1200 context()->Plug(v0); |
| 1309 break; | 1201 break; |
| 1310 } | 1202 } |
| 1311 context()->Plug(var); | 1203 context()->Plug(var); |
| 1312 break; | 1204 break; |
| 1313 } | 1205 } |
| 1314 | 1206 |
| 1315 case VariableLocation::LOOKUP: { | 1207 case VariableLocation::LOOKUP: |
| 1316 Comment cmnt(masm_, "[ Lookup variable"); | |
| 1317 Label done, slow; | |
| 1318 // Generate code for loading from variables potentially shadowed | |
| 1319 // by eval-introduced variables. | |
| 1320 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | |
| 1321 __ bind(&slow); | |
| 1322 __ Push(var->name()); | |
| 1323 Runtime::FunctionId function_id = | |
| 1324 typeof_mode == NOT_INSIDE_TYPEOF | |
| 1325 ? Runtime::kLoadLookupSlot | |
| 1326 : Runtime::kLoadLookupSlotInsideTypeof; | |
| 1327 __ CallRuntime(function_id); | |
| 1328 __ bind(&done); | |
| 1329 context()->Plug(v0); | |
| 1330 break; | |
| 1331 } | |
| 1332 | |
| 1333 case VariableLocation::MODULE: | 1208 case VariableLocation::MODULE: |
| 1334 UNREACHABLE(); | 1209 UNREACHABLE(); |
| 1335 } | 1210 } |
| 1336 } | 1211 } |
| 1337 | 1212 |
| 1338 | 1213 |
| 1339 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { | 1214 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { |
| 1340 Expression* expression = (property == NULL) ? NULL : property->value(); | 1215 Expression* expression = (property == NULL) ? NULL : property->value(); |
| 1341 if (expression == NULL) { | 1216 if (expression == NULL) { |
| 1342 __ LoadRoot(a1, Heap::kNullValueRootIndex); | 1217 __ LoadRoot(a1, Heap::kNullValueRootIndex); |
| (...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2104 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1979 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2105 __ Branch(&uninitialized_this, eq, a3, Operand(at)); | 1980 __ Branch(&uninitialized_this, eq, a3, Operand(at)); |
| 2106 __ li(a0, Operand(var->name())); | 1981 __ li(a0, Operand(var->name())); |
| 2107 __ Push(a0); | 1982 __ Push(a0); |
| 2108 __ CallRuntime(Runtime::kThrowReferenceError); | 1983 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2109 __ bind(&uninitialized_this); | 1984 __ bind(&uninitialized_this); |
| 2110 EmitStoreToStackLocalOrContextSlot(var, location); | 1985 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2111 | 1986 |
| 2112 } else { | 1987 } else { |
| 2113 DCHECK(var->mode() != CONST || op == Token::INIT); | 1988 DCHECK(var->mode() != CONST || op == Token::INIT); |
| 2114 if (var->IsLookupSlot()) { | 1989 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
| 2115 // Assignment to var. | 1990 DCHECK(!var->IsLookupSlot()); |
| 2116 __ Push(var->name()); | 1991 // Assignment to var or initializing assignment to let/const in harmony |
| 2117 __ Push(v0); | 1992 // mode. |
| 2118 __ CallRuntime(is_strict(language_mode()) | 1993 MemOperand location = VarOperand(var, a1); |
| 2119 ? Runtime::kStoreLookupSlot_Strict | 1994 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
| 2120 : Runtime::kStoreLookupSlot_Sloppy); | 1995 // Check for an uninitialized let binding. |
| 2121 } else { | 1996 __ lw(a2, location); |
| 2122 // Assignment to var or initializing assignment to let/const in harmony | 1997 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
| 2123 // mode. | 1998 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); |
| 2124 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | |
| 2125 MemOperand location = VarOperand(var, a1); | |
| 2126 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | |
| 2127 // Check for an uninitialized let binding. | |
| 2128 __ lw(a2, location); | |
| 2129 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | |
| 2130 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); | |
| 2131 } | |
| 2132 EmitStoreToStackLocalOrContextSlot(var, location); | |
| 2133 } | 1999 } |
| 2000 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2134 } | 2001 } |
| 2135 } | 2002 } |
| 2136 | 2003 |
| 2137 | 2004 |
| 2138 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2005 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2139 // Assignment to a property, using a named store IC. | 2006 // Assignment to a property, using a named store IC. |
| 2140 Property* prop = expr->target()->AsProperty(); | 2007 Property* prop = expr->target()->AsProperty(); |
| 2141 DCHECK(prop != NULL); | 2008 DCHECK(prop != NULL); |
| 2142 DCHECK(prop->key()->IsLiteral()); | 2009 DCHECK(prop->key()->IsLiteral()); |
| 2143 | 2010 |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2354 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2221 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2355 __ li(a0, Operand(arg_count)); | 2222 __ li(a0, Operand(arg_count)); |
| 2356 CallIC(code); | 2223 CallIC(code); |
| 2357 OperandStackDepthDecrement(arg_count + 1); | 2224 OperandStackDepthDecrement(arg_count + 1); |
| 2358 | 2225 |
| 2359 RecordJSReturnSite(expr); | 2226 RecordJSReturnSite(expr); |
| 2360 RestoreContext(); | 2227 RestoreContext(); |
| 2361 context()->DropAndPlug(1, v0); | 2228 context()->DropAndPlug(1, v0); |
| 2362 } | 2229 } |
| 2363 | 2230 |
| 2364 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { | |
| 2365 int arg_count = expr->arguments()->length(); | |
| 2366 // t4: copy of the first argument or undefined if it doesn't exist. | |
| 2367 if (arg_count > 0) { | |
| 2368 __ lw(t4, MemOperand(sp, arg_count * kPointerSize)); | |
| 2369 } else { | |
| 2370 __ LoadRoot(t4, Heap::kUndefinedValueRootIndex); | |
| 2371 } | |
| 2372 | |
| 2373 // t3: the receiver of the enclosing function. | |
| 2374 __ lw(t3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | |
| 2375 | |
| 2376 // t2: the language mode. | |
| 2377 __ li(t2, Operand(Smi::FromInt(language_mode()))); | |
| 2378 | |
| 2379 // t1: the start position of the scope the calls resides in. | |
| 2380 __ li(t1, Operand(Smi::FromInt(scope()->start_position()))); | |
| 2381 | |
| 2382 // t0: the source position of the eval call. | |
| 2383 __ li(t0, Operand(Smi::FromInt(expr->position()))); | |
| 2384 | |
| 2385 // Do the runtime call. | |
| 2386 __ Push(t4, t3, t2, t1, t0); | |
| 2387 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); | |
| 2388 } | |
| 2389 | |
| 2390 | |
| 2391 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | |
| 2392 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | |
| 2393 VariableProxy* callee = expr->expression()->AsVariableProxy(); | |
| 2394 if (callee->var()->IsLookupSlot()) { | |
| 2395 Label slow, done; | |
| 2396 | |
| 2397 SetExpressionPosition(callee); | |
| 2398 // Generate code for loading from variables potentially shadowed by | |
| 2399 // eval-introduced variables. | |
| 2400 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | |
| 2401 | |
| 2402 __ bind(&slow); | |
| 2403 // Call the runtime to find the function to call (returned in v0) | |
| 2404 // and the object holding it (returned in v1). | |
| 2405 __ Push(callee->name()); | |
| 2406 __ CallRuntime(Runtime::kLoadLookupSlotForCall); | |
| 2407 PushOperands(v0, v1); // Function, receiver. | |
| 2408 PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS); | |
| 2409 | |
| 2410 // If fast case code has been generated, emit code to push the | |
| 2411 // function and receiver and have the slow path jump around this | |
| 2412 // code. | |
| 2413 if (done.is_linked()) { | |
| 2414 Label call; | |
| 2415 __ Branch(&call); | |
| 2416 __ bind(&done); | |
| 2417 // Push function. | |
| 2418 __ push(v0); | |
| 2419 // The receiver is implicitly the global receiver. Indicate this | |
| 2420 // by passing the hole to the call function stub. | |
| 2421 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); | |
| 2422 __ push(a1); | |
| 2423 __ bind(&call); | |
| 2424 } | |
| 2425 } else { | |
| 2426 VisitForStackValue(callee); | |
| 2427 // refEnv.WithBaseObject() | |
| 2428 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); | |
| 2429 PushOperand(a2); // Reserved receiver slot. | |
| 2430 } | |
| 2431 } | |
| 2432 | |
| 2433 | |
| 2434 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) { | |
| 2435 // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval | |
| 2436 // to resolve the function we need to call. Then we call the resolved | |
| 2437 // function using the given arguments. | |
| 2438 ZoneList<Expression*>* args = expr->arguments(); | |
| 2439 int arg_count = args->length(); | |
| 2440 PushCalleeAndWithBaseObject(expr); | |
| 2441 | |
| 2442 // Push the arguments. | |
| 2443 for (int i = 0; i < arg_count; i++) { | |
| 2444 VisitForStackValue(args->at(i)); | |
| 2445 } | |
| 2446 | |
| 2447 // Push a copy of the function (found below the arguments) and | |
| 2448 // resolve eval. | |
| 2449 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | |
| 2450 __ push(a1); | |
| 2451 EmitResolvePossiblyDirectEval(expr); | |
| 2452 | |
| 2453 // Touch up the stack with the resolved function. | |
| 2454 __ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize)); | |
| 2455 | |
| 2456 PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS); | |
| 2457 // Record source position for debugger. | |
| 2458 SetCallPosition(expr); | |
| 2459 Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny, | |
| 2460 expr->tail_call_mode()) | |
| 2461 .code(); | |
| 2462 __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackICSlot()))); | |
| 2463 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | |
| 2464 __ li(a0, Operand(arg_count)); | |
| 2465 __ Call(code, RelocInfo::CODE_TARGET); | |
| 2466 OperandStackDepthDecrement(arg_count + 1); | |
| 2467 RecordJSReturnSite(expr); | |
| 2468 RestoreContext(); | |
| 2469 context()->DropAndPlug(1, v0); | |
| 2470 } | |
| 2471 | |
| 2472 | |
| 2473 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2231 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
| 2474 Comment cmnt(masm_, "[ CallNew"); | 2232 Comment cmnt(masm_, "[ CallNew"); |
| 2475 // According to ECMA-262, section 11.2.2, page 44, the function | 2233 // According to ECMA-262, section 11.2.2, page 44, the function |
| 2476 // expression in new calls must be evaluated before the | 2234 // expression in new calls must be evaluated before the |
| 2477 // arguments. | 2235 // arguments. |
| 2478 | 2236 |
| 2479 // Push constructor on the stack. If it's not a function it's used as | 2237 // Push constructor on the stack. If it's not a function it's used as |
| 2480 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is | 2238 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is |
| 2481 // ignored.g | 2239 // ignored.g |
| 2482 DCHECK(!expr->expression()->IsSuperPropertyReference()); | 2240 DCHECK(!expr->expression()->IsSuperPropertyReference()); |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2892 // Delete of an unqualified identifier is disallowed in strict mode but | 2650 // Delete of an unqualified identifier is disallowed in strict mode but |
| 2893 // "delete this" is allowed. | 2651 // "delete this" is allowed. |
| 2894 bool is_this = var->is_this(); | 2652 bool is_this = var->is_this(); |
| 2895 DCHECK(is_sloppy(language_mode()) || is_this); | 2653 DCHECK(is_sloppy(language_mode()) || is_this); |
| 2896 if (var->IsUnallocated()) { | 2654 if (var->IsUnallocated()) { |
| 2897 __ LoadGlobalObject(a2); | 2655 __ LoadGlobalObject(a2); |
| 2898 __ li(a1, Operand(var->name())); | 2656 __ li(a1, Operand(var->name())); |
| 2899 __ Push(a2, a1); | 2657 __ Push(a2, a1); |
| 2900 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); | 2658 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
| 2901 context()->Plug(v0); | 2659 context()->Plug(v0); |
| 2902 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 2660 } else { |
| 2661 DCHECK(!var->IsLookupSlot()); |
| 2662 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2903 // Result of deleting non-global, non-dynamic variables is false. | 2663 // Result of deleting non-global, non-dynamic variables is false. |
| 2904 // The subexpression does not have side effects. | 2664 // The subexpression does not have side effects. |
| 2905 context()->Plug(is_this); | 2665 context()->Plug(is_this); |
| 2906 } else { | |
| 2907 // Non-global variable. Call the runtime to try to delete from the | |
| 2908 // context where the variable was introduced. | |
| 2909 __ Push(var->name()); | |
| 2910 __ CallRuntime(Runtime::kDeleteLookupSlot); | |
| 2911 context()->Plug(v0); | |
| 2912 } | 2666 } |
| 2913 } else { | 2667 } else { |
| 2914 // Result of deleting non-property, non-variable reference is true. | 2668 // Result of deleting non-property, non-variable reference is true. |
| 2915 // The subexpression may have side effects. | 2669 // The subexpression may have side effects. |
| 2916 VisitForEffect(expr->expression()); | 2670 VisitForEffect(expr->expression()); |
| 2917 context()->Plug(true); | 2671 context()->Plug(true); |
| 2918 } | 2672 } |
| 2919 break; | 2673 break; |
| 2920 } | 2674 } |
| 2921 | 2675 |
| (...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3594 reinterpret_cast<uint32_t>( | 3348 reinterpret_cast<uint32_t>( |
| 3595 isolate->builtins()->OnStackReplacement()->entry())); | 3349 isolate->builtins()->OnStackReplacement()->entry())); |
| 3596 return ON_STACK_REPLACEMENT; | 3350 return ON_STACK_REPLACEMENT; |
| 3597 } | 3351 } |
| 3598 | 3352 |
| 3599 | 3353 |
| 3600 } // namespace internal | 3354 } // namespace internal |
| 3601 } // namespace v8 | 3355 } // namespace v8 |
| 3602 | 3356 |
| 3603 #endif // V8_TARGET_ARCH_MIPS | 3357 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |