OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_PPC | 5 #if V8_TARGET_ARCH_PPC |
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 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 if (variable->binding_needs_init()) { | 769 if (variable->binding_needs_init()) { |
770 Comment cmnt(masm_, "[ VariableDeclaration"); | 770 Comment cmnt(masm_, "[ VariableDeclaration"); |
771 EmitDebugCheckDeclarationContext(variable); | 771 EmitDebugCheckDeclarationContext(variable); |
772 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 772 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
773 __ StoreP(ip, ContextMemOperand(cp, variable->index()), r0); | 773 __ StoreP(ip, ContextMemOperand(cp, variable->index()), r0); |
774 // No write barrier since the_hole_value is in old space. | 774 // No write barrier since the_hole_value is in old space. |
775 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 775 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
776 } | 776 } |
777 break; | 777 break; |
778 | 778 |
779 case VariableLocation::LOOKUP: { | 779 case VariableLocation::LOOKUP: |
780 Comment cmnt(masm_, "[ VariableDeclaration"); | |
781 DCHECK_EQ(VAR, variable->mode()); | |
782 DCHECK(!variable->binding_needs_init()); | |
783 __ mov(r5, Operand(variable->name())); | |
784 __ Push(r5); | |
785 __ CallRuntime(Runtime::kDeclareEvalVar); | |
786 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | |
787 break; | |
788 } | |
789 | |
790 case VariableLocation::MODULE: | 780 case VariableLocation::MODULE: |
791 UNREACHABLE(); | 781 UNREACHABLE(); |
792 } | 782 } |
793 } | 783 } |
794 | 784 |
795 | 785 |
796 void FullCodeGenerator::VisitFunctionDeclaration( | 786 void FullCodeGenerator::VisitFunctionDeclaration( |
797 FunctionDeclaration* declaration) { | 787 FunctionDeclaration* declaration) { |
798 VariableProxy* proxy = declaration->proxy(); | 788 VariableProxy* proxy = declaration->proxy(); |
799 Variable* variable = proxy->var(); | 789 Variable* variable = proxy->var(); |
(...skipping 27 matching lines...) Expand all Loading... |
827 r0); | 817 r0); |
828 int offset = Context::SlotOffset(variable->index()); | 818 int offset = Context::SlotOffset(variable->index()); |
829 // We know that we have written a function, which is not a smi. | 819 // We know that we have written a function, which is not a smi. |
830 __ RecordWriteContextSlot(cp, offset, result_register(), r5, | 820 __ RecordWriteContextSlot(cp, offset, result_register(), r5, |
831 kLRHasBeenSaved, kDontSaveFPRegs, | 821 kLRHasBeenSaved, kDontSaveFPRegs, |
832 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 822 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
833 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 823 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
834 break; | 824 break; |
835 } | 825 } |
836 | 826 |
837 case VariableLocation::LOOKUP: { | 827 case VariableLocation::LOOKUP: |
838 Comment cmnt(masm_, "[ FunctionDeclaration"); | |
839 __ mov(r5, Operand(variable->name())); | |
840 PushOperand(r5); | |
841 // Push initial value for function declaration. | |
842 VisitForStackValue(declaration->fun()); | |
843 CallRuntimeWithOperands(Runtime::kDeclareEvalFunction); | |
844 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | |
845 break; | |
846 } | |
847 | |
848 case VariableLocation::MODULE: | 828 case VariableLocation::MODULE: |
849 UNREACHABLE(); | 829 UNREACHABLE(); |
850 } | 830 } |
851 } | 831 } |
852 | 832 |
853 | 833 |
854 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 834 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
855 // Call the runtime to declare the globals. | 835 // Call the runtime to declare the globals. |
856 __ mov(r4, Operand(pairs)); | 836 __ mov(r4, Operand(pairs)); |
857 __ LoadSmiLiteral(r3, Smi::FromInt(DeclareGlobalsFlags())); | 837 __ LoadSmiLiteral(r3, Smi::FromInt(DeclareGlobalsFlags())); |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, | 1128 void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, |
1149 int offset, | 1129 int offset, |
1150 FeedbackVectorSlot slot) { | 1130 FeedbackVectorSlot slot) { |
1151 DCHECK(NeedsHomeObject(initializer)); | 1131 DCHECK(NeedsHomeObject(initializer)); |
1152 __ Move(StoreDescriptor::ReceiverRegister(), r3); | 1132 __ Move(StoreDescriptor::ReceiverRegister(), r3); |
1153 __ LoadP(StoreDescriptor::ValueRegister(), | 1133 __ LoadP(StoreDescriptor::ValueRegister(), |
1154 MemOperand(sp, offset * kPointerSize)); | 1134 MemOperand(sp, offset * kPointerSize)); |
1155 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); | 1135 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); |
1156 } | 1136 } |
1157 | 1137 |
1158 | |
1159 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, | |
1160 TypeofMode typeof_mode, | |
1161 Label* slow) { | |
1162 Register current = cp; | |
1163 Register next = r4; | |
1164 Register temp = r5; | |
1165 | |
1166 int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval(); | |
1167 for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) { | |
1168 if (!s->NeedsContext()) continue; | |
1169 if (s->calls_sloppy_eval()) { | |
1170 // Check that extension is "the hole". | |
1171 __ LoadP(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); | |
1172 __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); | |
1173 } | |
1174 // Load next context in chain. | |
1175 __ LoadP(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); | |
1176 // Walk the rest of the chain without clobbering cp. | |
1177 current = next; | |
1178 to_check--; | |
1179 } | |
1180 | |
1181 // All extension objects were empty and it is safe to use a normal global | |
1182 // load machinery. | |
1183 EmitGlobalVariableLoad(proxy, typeof_mode); | |
1184 } | |
1185 | |
1186 | |
1187 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | |
1188 Label* slow) { | |
1189 DCHECK(var->IsContextSlot()); | |
1190 Register context = cp; | |
1191 Register next = r6; | |
1192 Register temp = r7; | |
1193 | |
1194 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | |
1195 if (s->NeedsContext()) { | |
1196 if (s->calls_sloppy_eval()) { | |
1197 // Check that extension is "the hole". | |
1198 __ LoadP(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); | |
1199 __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); | |
1200 } | |
1201 __ LoadP(next, ContextMemOperand(context, Context::PREVIOUS_INDEX)); | |
1202 // Walk the rest of the chain without clobbering cp. | |
1203 context = next; | |
1204 } | |
1205 } | |
1206 // Check that last extension is "the hole". | |
1207 __ LoadP(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); | |
1208 __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); | |
1209 | |
1210 // This function is used only for loads, not stores, so it's safe to | |
1211 // return an cp-based operand (the write barrier cannot be allowed to | |
1212 // destroy the cp register). | |
1213 return ContextMemOperand(context, var->index()); | |
1214 } | |
1215 | |
1216 | |
1217 void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, | |
1218 TypeofMode typeof_mode, | |
1219 Label* slow, Label* done) { | |
1220 // Generate fast-case code for variables that might be shadowed by | |
1221 // eval-introduced variables. Eval is used a lot without | |
1222 // introducing variables. In those cases, we do not want to | |
1223 // perform a runtime call for all variables in the scope | |
1224 // containing the eval. | |
1225 Variable* var = proxy->var(); | |
1226 if (var->mode() == DYNAMIC_GLOBAL) { | |
1227 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); | |
1228 __ b(done); | |
1229 } else if (var->mode() == DYNAMIC_LOCAL) { | |
1230 Variable* local = var->local_if_not_shadowed(); | |
1231 __ LoadP(r3, ContextSlotOperandCheckExtensions(local, slow)); | |
1232 if (local->binding_needs_init()) { | |
1233 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | |
1234 __ bne(done); | |
1235 __ mov(r3, Operand(var->name())); | |
1236 __ push(r3); | |
1237 __ CallRuntime(Runtime::kThrowReferenceError); | |
1238 } else { | |
1239 __ b(done); | |
1240 } | |
1241 } | |
1242 } | |
1243 | |
1244 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1138 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
1245 TypeofMode typeof_mode) { | 1139 TypeofMode typeof_mode) { |
1246 // Record position before possible IC call. | 1140 // Record position before possible IC call. |
1247 SetExpressionPosition(proxy); | 1141 SetExpressionPosition(proxy); |
1248 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 1142 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); |
1249 Variable* var = proxy->var(); | 1143 Variable* var = proxy->var(); |
1250 | 1144 |
1251 // Three cases: global variables, lookup variables, and all other types of | 1145 // Two cases: global variables and all other types of variables. |
1252 // variables. | |
1253 switch (var->location()) { | 1146 switch (var->location()) { |
1254 case VariableLocation::UNALLOCATED: { | 1147 case VariableLocation::UNALLOCATED: { |
1255 Comment cmnt(masm_, "[ Global variable"); | 1148 Comment cmnt(masm_, "[ Global variable"); |
1256 EmitGlobalVariableLoad(proxy, typeof_mode); | 1149 EmitGlobalVariableLoad(proxy, typeof_mode); |
1257 context()->Plug(r3); | 1150 context()->Plug(r3); |
1258 break; | 1151 break; |
1259 } | 1152 } |
1260 | 1153 |
1261 case VariableLocation::PARAMETER: | 1154 case VariableLocation::PARAMETER: |
1262 case VariableLocation::LOCAL: | 1155 case VariableLocation::LOCAL: |
(...skipping 12 matching lines...) Expand all Loading... |
1275 __ push(r3); | 1168 __ push(r3); |
1276 __ CallRuntime(Runtime::kThrowReferenceError); | 1169 __ CallRuntime(Runtime::kThrowReferenceError); |
1277 __ bind(&done); | 1170 __ bind(&done); |
1278 context()->Plug(r3); | 1171 context()->Plug(r3); |
1279 break; | 1172 break; |
1280 } | 1173 } |
1281 context()->Plug(var); | 1174 context()->Plug(var); |
1282 break; | 1175 break; |
1283 } | 1176 } |
1284 | 1177 |
1285 case VariableLocation::LOOKUP: { | 1178 case VariableLocation::LOOKUP: |
1286 Comment cmnt(masm_, "[ Lookup variable"); | |
1287 Label done, slow; | |
1288 // Generate code for loading from variables potentially shadowed | |
1289 // by eval-introduced variables. | |
1290 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | |
1291 __ bind(&slow); | |
1292 __ Push(var->name()); | |
1293 Runtime::FunctionId function_id = | |
1294 typeof_mode == NOT_INSIDE_TYPEOF | |
1295 ? Runtime::kLoadLookupSlot | |
1296 : Runtime::kLoadLookupSlotInsideTypeof; | |
1297 __ CallRuntime(function_id); | |
1298 __ bind(&done); | |
1299 context()->Plug(r3); | |
1300 break; | |
1301 } | |
1302 | |
1303 case VariableLocation::MODULE: | 1179 case VariableLocation::MODULE: |
1304 UNREACHABLE(); | 1180 UNREACHABLE(); |
1305 } | 1181 } |
1306 } | 1182 } |
1307 | 1183 |
1308 | 1184 |
1309 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { | 1185 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { |
1310 Expression* expression = (property == NULL) ? NULL : property->value(); | 1186 Expression* expression = (property == NULL) ? NULL : property->value(); |
1311 if (expression == NULL) { | 1187 if (expression == NULL) { |
1312 __ LoadRoot(r4, Heap::kNullValueRootIndex); | 1188 __ LoadRoot(r4, Heap::kNullValueRootIndex); |
(...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2104 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); | 1980 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); |
2105 __ beq(&uninitialized_this); | 1981 __ beq(&uninitialized_this); |
2106 __ mov(r4, Operand(var->name())); | 1982 __ mov(r4, Operand(var->name())); |
2107 __ push(r4); | 1983 __ push(r4); |
2108 __ CallRuntime(Runtime::kThrowReferenceError); | 1984 __ CallRuntime(Runtime::kThrowReferenceError); |
2109 __ bind(&uninitialized_this); | 1985 __ bind(&uninitialized_this); |
2110 EmitStoreToStackLocalOrContextSlot(var, location); | 1986 EmitStoreToStackLocalOrContextSlot(var, location); |
2111 | 1987 |
2112 } else { | 1988 } else { |
2113 DCHECK(var->mode() != CONST || op == Token::INIT); | 1989 DCHECK(var->mode() != CONST || op == Token::INIT); |
2114 if (var->IsLookupSlot()) { | 1990 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
2115 // Assignment to var. | 1991 DCHECK(!var->IsLookupSlot()); |
2116 __ Push(var->name()); | 1992 // Assignment to var or initializing assignment to let/const in harmony |
2117 __ Push(r3); | 1993 // mode. |
2118 __ CallRuntime(is_strict(language_mode()) | 1994 MemOperand location = VarOperand(var, r4); |
2119 ? Runtime::kStoreLookupSlot_Strict | 1995 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
2120 : Runtime::kStoreLookupSlot_Sloppy); | 1996 // Check for an uninitialized let binding. |
2121 } else { | 1997 __ LoadP(r5, location); |
2122 // Assignment to var or initializing assignment to let/const in harmony | 1998 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
2123 // mode. | 1999 __ Check(eq, kLetBindingReInitialization); |
2124 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | |
2125 MemOperand location = VarOperand(var, r4); | |
2126 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | |
2127 // Check for an uninitialized let binding. | |
2128 __ LoadP(r5, location); | |
2129 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | |
2130 __ Check(eq, kLetBindingReInitialization); | |
2131 } | |
2132 EmitStoreToStackLocalOrContextSlot(var, location); | |
2133 } | 2000 } |
| 2001 EmitStoreToStackLocalOrContextSlot(var, location); |
2134 } | 2002 } |
2135 } | 2003 } |
2136 | 2004 |
2137 | 2005 |
2138 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2006 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2139 // Assignment to a property, using a named store IC. | 2007 // Assignment to a property, using a named store IC. |
2140 Property* prop = expr->target()->AsProperty(); | 2008 Property* prop = expr->target()->AsProperty(); |
2141 DCHECK(prop != NULL); | 2009 DCHECK(prop != NULL); |
2142 DCHECK(prop->key()->IsLiteral()); | 2010 DCHECK(prop->key()->IsLiteral()); |
2143 | 2011 |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2346 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | 2214 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); |
2347 __ mov(r3, Operand(arg_count)); | 2215 __ mov(r3, Operand(arg_count)); |
2348 CallIC(code); | 2216 CallIC(code); |
2349 OperandStackDepthDecrement(arg_count + 1); | 2217 OperandStackDepthDecrement(arg_count + 1); |
2350 | 2218 |
2351 RecordJSReturnSite(expr); | 2219 RecordJSReturnSite(expr); |
2352 RestoreContext(); | 2220 RestoreContext(); |
2353 context()->DropAndPlug(1, r3); | 2221 context()->DropAndPlug(1, r3); |
2354 } | 2222 } |
2355 | 2223 |
2356 | |
2357 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { | |
2358 int arg_count = expr->arguments()->length(); | |
2359 // r7: copy of the first argument or undefined if it doesn't exist. | |
2360 if (arg_count > 0) { | |
2361 __ LoadP(r7, MemOperand(sp, arg_count * kPointerSize), r0); | |
2362 } else { | |
2363 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); | |
2364 } | |
2365 | |
2366 // r6: the receiver of the enclosing function. | |
2367 __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | |
2368 | |
2369 // r5: language mode. | |
2370 __ LoadSmiLiteral(r5, Smi::FromInt(language_mode())); | |
2371 | |
2372 // r4: the start position of the scope the calls resides in. | |
2373 __ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position())); | |
2374 | |
2375 // r3: the source position of the eval call. | |
2376 __ LoadSmiLiteral(r3, Smi::FromInt(expr->position())); | |
2377 | |
2378 // Do the runtime call. | |
2379 __ Push(r7, r6, r5, r4, r3); | |
2380 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); | |
2381 } | |
2382 | |
2383 | |
2384 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | |
2385 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | |
2386 VariableProxy* callee = expr->expression()->AsVariableProxy(); | |
2387 if (callee->var()->IsLookupSlot()) { | |
2388 Label slow, done; | |
2389 SetExpressionPosition(callee); | |
2390 // Generate code for loading from variables potentially shadowed by | |
2391 // eval-introduced variables. | |
2392 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | |
2393 | |
2394 __ bind(&slow); | |
2395 // Call the runtime to find the function to call (returned in r3) and | |
2396 // the object holding it (returned in r4). | |
2397 __ Push(callee->name()); | |
2398 __ CallRuntime(Runtime::kLoadLookupSlotForCall); | |
2399 PushOperands(r3, r4); // Function, receiver. | |
2400 PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS); | |
2401 | |
2402 // If fast case code has been generated, emit code to push the function | |
2403 // and receiver and have the slow path jump around this code. | |
2404 if (done.is_linked()) { | |
2405 Label call; | |
2406 __ b(&call); | |
2407 __ bind(&done); | |
2408 // Push function. | |
2409 __ push(r3); | |
2410 // Pass undefined as the receiver, which is the WithBaseObject of a | |
2411 // non-object environment record. If the callee is sloppy, it will patch | |
2412 // it up to be the global receiver. | |
2413 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | |
2414 __ push(r4); | |
2415 __ bind(&call); | |
2416 } | |
2417 } else { | |
2418 VisitForStackValue(callee); | |
2419 // refEnv.WithBaseObject() | |
2420 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); | |
2421 PushOperand(r5); // Reserved receiver slot. | |
2422 } | |
2423 } | |
2424 | |
2425 | |
2426 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) { | |
2427 // In a call to eval, we first call | |
2428 // Runtime_ResolvePossiblyDirectEval to resolve the function we need | |
2429 // to call. Then we call the resolved function using the given arguments. | |
2430 ZoneList<Expression*>* args = expr->arguments(); | |
2431 int arg_count = args->length(); | |
2432 | |
2433 PushCalleeAndWithBaseObject(expr); | |
2434 | |
2435 // Push the arguments. | |
2436 for (int i = 0; i < arg_count; i++) { | |
2437 VisitForStackValue(args->at(i)); | |
2438 } | |
2439 | |
2440 // Push a copy of the function (found below the arguments) and | |
2441 // resolve eval. | |
2442 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | |
2443 __ push(r4); | |
2444 EmitResolvePossiblyDirectEval(expr); | |
2445 | |
2446 // Touch up the stack with the resolved function. | |
2447 __ StoreP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | |
2448 | |
2449 PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS); | |
2450 | |
2451 // Record source position for debugger. | |
2452 SetCallPosition(expr); | |
2453 Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny, | |
2454 expr->tail_call_mode()) | |
2455 .code(); | |
2456 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackICSlot())); | |
2457 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | |
2458 __ mov(r3, Operand(arg_count)); | |
2459 __ Call(code, RelocInfo::CODE_TARGET); | |
2460 OperandStackDepthDecrement(arg_count + 1); | |
2461 RecordJSReturnSite(expr); | |
2462 RestoreContext(); | |
2463 context()->DropAndPlug(1, r3); | |
2464 } | |
2465 | |
2466 | |
2467 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2224 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
2468 Comment cmnt(masm_, "[ CallNew"); | 2225 Comment cmnt(masm_, "[ CallNew"); |
2469 // According to ECMA-262, section 11.2.2, page 44, the function | 2226 // According to ECMA-262, section 11.2.2, page 44, the function |
2470 // expression in new calls must be evaluated before the | 2227 // expression in new calls must be evaluated before the |
2471 // arguments. | 2228 // arguments. |
2472 | 2229 |
2473 // Push constructor on the stack. If it's not a function it's used as | 2230 // Push constructor on the stack. If it's not a function it's used as |
2474 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is | 2231 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is |
2475 // ignored. | 2232 // ignored. |
2476 DCHECK(!expr->expression()->IsSuperPropertyReference()); | 2233 DCHECK(!expr->expression()->IsSuperPropertyReference()); |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2885 // Delete of an unqualified identifier is disallowed in strict mode but | 2642 // Delete of an unqualified identifier is disallowed in strict mode but |
2886 // "delete this" is allowed. | 2643 // "delete this" is allowed. |
2887 bool is_this = var->is_this(); | 2644 bool is_this = var->is_this(); |
2888 DCHECK(is_sloppy(language_mode()) || is_this); | 2645 DCHECK(is_sloppy(language_mode()) || is_this); |
2889 if (var->IsUnallocated()) { | 2646 if (var->IsUnallocated()) { |
2890 __ LoadGlobalObject(r5); | 2647 __ LoadGlobalObject(r5); |
2891 __ mov(r4, Operand(var->name())); | 2648 __ mov(r4, Operand(var->name())); |
2892 __ Push(r5, r4); | 2649 __ Push(r5, r4); |
2893 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); | 2650 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
2894 context()->Plug(r3); | 2651 context()->Plug(r3); |
2895 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 2652 } else { |
| 2653 DCHECK(!var->IsLookupSlot()); |
| 2654 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2896 // Result of deleting non-global, non-dynamic variables is false. | 2655 // Result of deleting non-global, non-dynamic variables is false. |
2897 // The subexpression does not have side effects. | 2656 // The subexpression does not have side effects. |
2898 context()->Plug(is_this); | 2657 context()->Plug(is_this); |
2899 } else { | |
2900 // Non-global variable. Call the runtime to try to delete from the | |
2901 // context where the variable was introduced. | |
2902 __ Push(var->name()); | |
2903 __ CallRuntime(Runtime::kDeleteLookupSlot); | |
2904 context()->Plug(r3); | |
2905 } | 2658 } |
2906 } else { | 2659 } else { |
2907 // Result of deleting non-property, non-variable reference is true. | 2660 // Result of deleting non-property, non-variable reference is true. |
2908 // The subexpression may have side effects. | 2661 // The subexpression may have side effects. |
2909 VisitForEffect(expr->expression()); | 2662 VisitForEffect(expr->expression()); |
2910 context()->Plug(true); | 2663 context()->Plug(true); |
2911 } | 2664 } |
2912 break; | 2665 break; |
2913 } | 2666 } |
2914 | 2667 |
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3576 | 3329 |
3577 DCHECK(Assembler::IsCrSet(Assembler::instr_at(cmp_address))); | 3330 DCHECK(Assembler::IsCrSet(Assembler::instr_at(cmp_address))); |
3578 | 3331 |
3579 DCHECK(interrupt_address == | 3332 DCHECK(interrupt_address == |
3580 isolate->builtins()->OnStackReplacement()->entry()); | 3333 isolate->builtins()->OnStackReplacement()->entry()); |
3581 return ON_STACK_REPLACEMENT; | 3334 return ON_STACK_REPLACEMENT; |
3582 } | 3335 } |
3583 } // namespace internal | 3336 } // namespace internal |
3584 } // namespace v8 | 3337 } // namespace v8 |
3585 #endif // V8_TARGET_ARCH_PPC | 3338 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |