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