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