| 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_ARM | 5 #if V8_TARGET_ARCH_ARM | 
| 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 790 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 801       if (variable->binding_needs_init()) { | 801       if (variable->binding_needs_init()) { | 
| 802         Comment cmnt(masm_, "[ VariableDeclaration"); | 802         Comment cmnt(masm_, "[ VariableDeclaration"); | 
| 803         EmitDebugCheckDeclarationContext(variable); | 803         EmitDebugCheckDeclarationContext(variable); | 
| 804         __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 804         __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 
| 805         __ str(r0, ContextMemOperand(cp, variable->index())); | 805         __ str(r0, ContextMemOperand(cp, variable->index())); | 
| 806         // No write barrier since the_hole_value is in old space. | 806         // No write barrier since the_hole_value is in old space. | 
| 807         PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 807         PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 
| 808       } | 808       } | 
| 809       break; | 809       break; | 
| 810 | 810 | 
| 811     case VariableLocation::LOOKUP: { | 811     case VariableLocation::LOOKUP: | 
| 812       Comment cmnt(masm_, "[ VariableDeclaration"); |  | 
| 813       DCHECK_EQ(VAR, variable->mode()); |  | 
| 814       DCHECK(!variable->binding_needs_init()); |  | 
| 815       __ mov(r2, Operand(variable->name())); |  | 
| 816       __ Push(r2); |  | 
| 817       __ CallRuntime(Runtime::kDeclareEvalVar); |  | 
| 818       PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |  | 
| 819       break; |  | 
| 820     } |  | 
| 821 |  | 
| 822     case VariableLocation::MODULE: | 812     case VariableLocation::MODULE: | 
| 823       UNREACHABLE(); | 813       UNREACHABLE(); | 
| 824   } | 814   } | 
| 825 } | 815 } | 
| 826 | 816 | 
| 827 | 817 | 
| 828 void FullCodeGenerator::VisitFunctionDeclaration( | 818 void FullCodeGenerator::VisitFunctionDeclaration( | 
| 829     FunctionDeclaration* declaration) { | 819     FunctionDeclaration* declaration) { | 
| 830   VariableProxy* proxy = declaration->proxy(); | 820   VariableProxy* proxy = declaration->proxy(); | 
| 831   Variable* variable = proxy->var(); | 821   Variable* variable = proxy->var(); | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 863                                 result_register(), | 853                                 result_register(), | 
| 864                                 r2, | 854                                 r2, | 
| 865                                 kLRHasBeenSaved, | 855                                 kLRHasBeenSaved, | 
| 866                                 kDontSaveFPRegs, | 856                                 kDontSaveFPRegs, | 
| 867                                 EMIT_REMEMBERED_SET, | 857                                 EMIT_REMEMBERED_SET, | 
| 868                                 OMIT_SMI_CHECK); | 858                                 OMIT_SMI_CHECK); | 
| 869       PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 859       PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 
| 870       break; | 860       break; | 
| 871     } | 861     } | 
| 872 | 862 | 
| 873     case VariableLocation::LOOKUP: { | 863     case VariableLocation::LOOKUP: | 
| 874       Comment cmnt(masm_, "[ FunctionDeclaration"); |  | 
| 875       __ mov(r2, Operand(variable->name())); |  | 
| 876       PushOperand(r2); |  | 
| 877       // Push initial value for function declaration. |  | 
| 878       VisitForStackValue(declaration->fun()); |  | 
| 879       CallRuntimeWithOperands(Runtime::kDeclareEvalFunction); |  | 
| 880       PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |  | 
| 881       break; |  | 
| 882     } |  | 
| 883 |  | 
| 884     case VariableLocation::MODULE: | 864     case VariableLocation::MODULE: | 
| 885       UNREACHABLE(); | 865       UNREACHABLE(); | 
| 886   } | 866   } | 
| 887 } | 867 } | 
| 888 | 868 | 
| 889 | 869 | 
| 890 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 870 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 
| 891   // Call the runtime to declare the globals. | 871   // Call the runtime to declare the globals. | 
| 892   __ mov(r1, Operand(pairs)); | 872   __ mov(r1, Operand(pairs)); | 
| 893   __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); | 873   __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); | 
| (...skipping 283 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(), r0); | 1161   __ Move(StoreDescriptor::ReceiverRegister(), r0); | 
| 1182   __ ldr(StoreDescriptor::ValueRegister(), | 1162   __ ldr(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 = r1; |  | 
| 1193   Register temp = r2; |  | 
| 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       __ ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); |  | 
| 1201       __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); |  | 
| 1202     } |  | 
| 1203     // Load next context in chain. |  | 
| 1204     __ ldr(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 = r3; |  | 
| 1221   Register temp = r4; |  | 
| 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         __ ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); |  | 
| 1228         __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); |  | 
| 1229       } |  | 
| 1230       __ ldr(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   __ ldr(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     __ jmp(done); |  | 
| 1258   } else if (var->mode() == DYNAMIC_LOCAL) { |  | 
| 1259     Variable* local = var->local_if_not_shadowed(); |  | 
| 1260     __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); |  | 
| 1261     if (local->binding_needs_init()) { |  | 
| 1262       __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); |  | 
| 1263       __ b(ne, done); |  | 
| 1264       __ mov(r0, Operand(var->name())); |  | 
| 1265       __ push(r0); |  | 
| 1266       __ CallRuntime(Runtime::kThrowReferenceError); |  | 
| 1267     } else { |  | 
| 1268       __ jmp(done); |  | 
| 1269     } |  | 
| 1270   } |  | 
| 1271 } |  | 
| 1272 |  | 
| 1273 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1167 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 
| 1274                                          TypeofMode typeof_mode) { | 1168                                          TypeofMode typeof_mode) { | 
| 1275   // Record position before possible IC call. | 1169   // Record position before possible IC call. | 
| 1276   SetExpressionPosition(proxy); | 1170   SetExpressionPosition(proxy); | 
| 1277   PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 1171   PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 
| 1278   Variable* var = proxy->var(); | 1172   Variable* var = proxy->var(); | 
| 1279 | 1173 | 
| 1280   // Three cases: global variables, lookup variables, and all other types of | 1174   // Two cases: global variables and all other types of variables. | 
| 1281   // variables. |  | 
| 1282   switch (var->location()) { | 1175   switch (var->location()) { | 
| 1283     case VariableLocation::UNALLOCATED: { | 1176     case VariableLocation::UNALLOCATED: { | 
| 1284       Comment cmnt(masm_, "[ Global variable"); | 1177       Comment cmnt(masm_, "[ Global variable"); | 
| 1285       EmitGlobalVariableLoad(proxy, typeof_mode); | 1178       EmitGlobalVariableLoad(proxy, typeof_mode); | 
| 1286       context()->Plug(r0); | 1179       context()->Plug(r0); | 
| 1287       break; | 1180       break; | 
| 1288     } | 1181     } | 
| 1289 | 1182 | 
| 1290     case VariableLocation::PARAMETER: | 1183     case VariableLocation::PARAMETER: | 
| 1291     case VariableLocation::LOCAL: | 1184     case VariableLocation::LOCAL: | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 1304         __ push(r0); | 1197         __ push(r0); | 
| 1305         __ CallRuntime(Runtime::kThrowReferenceError); | 1198         __ CallRuntime(Runtime::kThrowReferenceError); | 
| 1306         __ bind(&done); | 1199         __ bind(&done); | 
| 1307         context()->Plug(r0); | 1200         context()->Plug(r0); | 
| 1308         break; | 1201         break; | 
| 1309       } | 1202       } | 
| 1310       context()->Plug(var); | 1203       context()->Plug(var); | 
| 1311       break; | 1204       break; | 
| 1312     } | 1205     } | 
| 1313 | 1206 | 
| 1314     case VariableLocation::LOOKUP: { | 1207     case VariableLocation::LOOKUP: | 
| 1315       Comment cmnt(masm_, "[ Lookup variable"); |  | 
| 1316       Label done, slow; |  | 
| 1317       // Generate code for loading from variables potentially shadowed |  | 
| 1318       // by eval-introduced variables. |  | 
| 1319       EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); |  | 
| 1320       __ bind(&slow); |  | 
| 1321       __ Push(var->name()); |  | 
| 1322       Runtime::FunctionId function_id = |  | 
| 1323           typeof_mode == NOT_INSIDE_TYPEOF |  | 
| 1324               ? Runtime::kLoadLookupSlot |  | 
| 1325               : Runtime::kLoadLookupSlotInsideTypeof; |  | 
| 1326       __ CallRuntime(function_id); |  | 
| 1327       __ bind(&done); |  | 
| 1328       context()->Plug(r0); |  | 
| 1329       break; |  | 
| 1330     } |  | 
| 1331 |  | 
| 1332     case VariableLocation::MODULE: | 1208     case VariableLocation::MODULE: | 
| 1333       UNREACHABLE(); | 1209       UNREACHABLE(); | 
| 1334   } | 1210   } | 
| 1335 } | 1211 } | 
| 1336 | 1212 | 
| 1337 | 1213 | 
| 1338 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { | 1214 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { | 
| 1339   Expression* expression = (property == NULL) ? NULL : property->value(); | 1215   Expression* expression = (property == NULL) ? NULL : property->value(); | 
| 1340   if (expression == NULL) { | 1216   if (expression == NULL) { | 
| 1341     __ LoadRoot(r1, Heap::kNullValueRootIndex); | 1217     __ LoadRoot(r1, Heap::kNullValueRootIndex); | 
| (...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2092     __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 1968     __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 
| 2093     __ b(eq, &uninitialized_this); | 1969     __ b(eq, &uninitialized_this); | 
| 2094     __ mov(r0, Operand(var->name())); | 1970     __ mov(r0, Operand(var->name())); | 
| 2095     __ Push(r0); | 1971     __ Push(r0); | 
| 2096     __ CallRuntime(Runtime::kThrowReferenceError); | 1972     __ CallRuntime(Runtime::kThrowReferenceError); | 
| 2097     __ bind(&uninitialized_this); | 1973     __ bind(&uninitialized_this); | 
| 2098     EmitStoreToStackLocalOrContextSlot(var, location); | 1974     EmitStoreToStackLocalOrContextSlot(var, location); | 
| 2099 | 1975 | 
| 2100   } else { | 1976   } else { | 
| 2101     DCHECK(var->mode() != CONST || op == Token::INIT); | 1977     DCHECK(var->mode() != CONST || op == Token::INIT); | 
| 2102     if (var->IsLookupSlot()) { | 1978     DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 
| 2103       // Assignment to var. | 1979     DCHECK(!var->IsLookupSlot()); | 
| 2104       __ Push(var->name()); | 1980     // Assignment to var or initializing assignment to let/const in harmony | 
| 2105       __ Push(r0); | 1981     // mode. | 
| 2106       __ CallRuntime(is_strict(language_mode()) | 1982     MemOperand location = VarOperand(var, r1); | 
| 2107                          ? Runtime::kStoreLookupSlot_Strict | 1983     if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | 
| 2108                          : Runtime::kStoreLookupSlot_Sloppy); | 1984       // Check for an uninitialized let binding. | 
| 2109     } else { | 1985       __ ldr(r2, location); | 
| 2110       // Assignment to var or initializing assignment to let/const in harmony | 1986       __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 
| 2111       // mode. | 1987       __ Check(eq, kLetBindingReInitialization); | 
| 2112       DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |  | 
| 2113       MemOperand location = VarOperand(var, r1); |  | 
| 2114       if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |  | 
| 2115         // Check for an uninitialized let binding. |  | 
| 2116         __ ldr(r2, location); |  | 
| 2117         __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); |  | 
| 2118         __ Check(eq, kLetBindingReInitialization); |  | 
| 2119       } |  | 
| 2120       EmitStoreToStackLocalOrContextSlot(var, location); |  | 
| 2121     } | 1988     } | 
|  | 1989     EmitStoreToStackLocalOrContextSlot(var, location); | 
| 2122   } | 1990   } | 
| 2123 } | 1991 } | 
| 2124 | 1992 | 
| 2125 | 1993 | 
| 2126 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1994 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 
| 2127   // Assignment to a property, using a named store IC. | 1995   // Assignment to a property, using a named store IC. | 
| 2128   Property* prop = expr->target()->AsProperty(); | 1996   Property* prop = expr->target()->AsProperty(); | 
| 2129   DCHECK(prop != NULL); | 1997   DCHECK(prop != NULL); | 
| 2130   DCHECK(prop->key()->IsLiteral()); | 1998   DCHECK(prop->key()->IsLiteral()); | 
| 2131 | 1999 | 
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2338   __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2206   __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 
| 2339   __ mov(r0, Operand(arg_count)); | 2207   __ mov(r0, Operand(arg_count)); | 
| 2340   CallIC(code); | 2208   CallIC(code); | 
| 2341   OperandStackDepthDecrement(arg_count + 1); | 2209   OperandStackDepthDecrement(arg_count + 1); | 
| 2342 | 2210 | 
| 2343   RecordJSReturnSite(expr); | 2211   RecordJSReturnSite(expr); | 
| 2344   RestoreContext(); | 2212   RestoreContext(); | 
| 2345   context()->DropAndPlug(1, r0); | 2213   context()->DropAndPlug(1, r0); | 
| 2346 } | 2214 } | 
| 2347 | 2215 | 
| 2348 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { |  | 
| 2349   int arg_count = expr->arguments()->length(); |  | 
| 2350   // r4: copy of the first argument or undefined if it doesn't exist. |  | 
| 2351   if (arg_count > 0) { |  | 
| 2352     __ ldr(r4, MemOperand(sp, arg_count * kPointerSize)); |  | 
| 2353   } else { |  | 
| 2354     __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); |  | 
| 2355   } |  | 
| 2356 |  | 
| 2357   // r3: the receiver of the enclosing function. |  | 
| 2358   __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |  | 
| 2359 |  | 
| 2360   // r2: language mode. |  | 
| 2361   __ mov(r2, Operand(Smi::FromInt(language_mode()))); |  | 
| 2362 |  | 
| 2363   // r1: the start position of the scope the calls resides in. |  | 
| 2364   __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); |  | 
| 2365 |  | 
| 2366   // r0: the source position of the eval call. |  | 
| 2367   __ mov(r0, Operand(Smi::FromInt(expr->position()))); |  | 
| 2368 |  | 
| 2369   // Do the runtime call. |  | 
| 2370   __ Push(r4, r3, r2, r1, r0); |  | 
| 2371   __ CallRuntime(Runtime::kResolvePossiblyDirectEval); |  | 
| 2372 } |  | 
| 2373 |  | 
| 2374 |  | 
| 2375 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. |  | 
| 2376 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |  | 
| 2377   VariableProxy* callee = expr->expression()->AsVariableProxy(); |  | 
| 2378   if (callee->var()->IsLookupSlot()) { |  | 
| 2379     Label slow, done; |  | 
| 2380     SetExpressionPosition(callee); |  | 
| 2381     // Generate code for loading from variables potentially shadowed |  | 
| 2382     // by eval-introduced variables. |  | 
| 2383     EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |  | 
| 2384 |  | 
| 2385     __ bind(&slow); |  | 
| 2386     // Call the runtime to find the function to call (returned in r0) |  | 
| 2387     // and the object holding it (returned in edx). |  | 
| 2388     __ Push(callee->name()); |  | 
| 2389     __ CallRuntime(Runtime::kLoadLookupSlotForCall); |  | 
| 2390     PushOperands(r0, r1);  // Function, receiver. |  | 
| 2391     PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS); |  | 
| 2392 |  | 
| 2393     // If fast case code has been generated, emit code to push the |  | 
| 2394     // function and receiver and have the slow path jump around this |  | 
| 2395     // code. |  | 
| 2396     if (done.is_linked()) { |  | 
| 2397       Label call; |  | 
| 2398       __ b(&call); |  | 
| 2399       __ bind(&done); |  | 
| 2400       // Push function. |  | 
| 2401       __ push(r0); |  | 
| 2402       // The receiver is implicitly the global receiver. Indicate this |  | 
| 2403       // by passing the hole to the call function stub. |  | 
| 2404       __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |  | 
| 2405       __ push(r1); |  | 
| 2406       __ bind(&call); |  | 
| 2407     } |  | 
| 2408   } else { |  | 
| 2409     VisitForStackValue(callee); |  | 
| 2410     // refEnv.WithBaseObject() |  | 
| 2411     __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |  | 
| 2412     PushOperand(r2);  // Reserved receiver slot. |  | 
| 2413   } |  | 
| 2414 } |  | 
| 2415 |  | 
| 2416 |  | 
| 2417 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) { |  | 
| 2418   // In a call to eval, we first call |  | 
| 2419   // Runtime_ResolvePossiblyDirectEval to resolve the function we need |  | 
| 2420   // to call.  Then we call the resolved function using the given arguments. |  | 
| 2421   ZoneList<Expression*>* args = expr->arguments(); |  | 
| 2422   int arg_count = args->length(); |  | 
| 2423 |  | 
| 2424   PushCalleeAndWithBaseObject(expr); |  | 
| 2425 |  | 
| 2426   // Push the arguments. |  | 
| 2427   for (int i = 0; i < arg_count; i++) { |  | 
| 2428     VisitForStackValue(args->at(i)); |  | 
| 2429   } |  | 
| 2430 |  | 
| 2431   // Push a copy of the function (found below the arguments) and |  | 
| 2432   // resolve eval. |  | 
| 2433   __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |  | 
| 2434   __ push(r1); |  | 
| 2435   EmitResolvePossiblyDirectEval(expr); |  | 
| 2436 |  | 
| 2437   // Touch up the stack with the resolved function. |  | 
| 2438   __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); |  | 
| 2439 |  | 
| 2440   PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS); |  | 
| 2441 |  | 
| 2442   // Record source position for debugger. |  | 
| 2443   SetCallPosition(expr); |  | 
| 2444   Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny, |  | 
| 2445                                           expr->tail_call_mode()) |  | 
| 2446                           .code(); |  | 
| 2447   __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot()))); |  | 
| 2448   __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |  | 
| 2449   __ mov(r0, Operand(arg_count)); |  | 
| 2450   __ Call(code, RelocInfo::CODE_TARGET); |  | 
| 2451   OperandStackDepthDecrement(arg_count + 1); |  | 
| 2452   RecordJSReturnSite(expr); |  | 
| 2453   RestoreContext(); |  | 
| 2454   context()->DropAndPlug(1, r0); |  | 
| 2455 } |  | 
| 2456 |  | 
| 2457 |  | 
| 2458 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2216 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 
| 2459   Comment cmnt(masm_, "[ CallNew"); | 2217   Comment cmnt(masm_, "[ CallNew"); | 
| 2460   // According to ECMA-262, section 11.2.2, page 44, the function | 2218   // According to ECMA-262, section 11.2.2, page 44, the function | 
| 2461   // expression in new calls must be evaluated before the | 2219   // expression in new calls must be evaluated before the | 
| 2462   // arguments. | 2220   // arguments. | 
| 2463 | 2221 | 
| 2464   // Push constructor on the stack.  If it's not a function it's used as | 2222   // Push constructor on the stack.  If it's not a function it's used as | 
| 2465   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is | 2223   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is | 
| 2466   // ignored. | 2224   // ignored. | 
| 2467   DCHECK(!expr->expression()->IsSuperPropertyReference()); | 2225   DCHECK(!expr->expression()->IsSuperPropertyReference()); | 
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2876         // Delete of an unqualified identifier is disallowed in strict mode but | 2634         // Delete of an unqualified identifier is disallowed in strict mode but | 
| 2877         // "delete this" is allowed. | 2635         // "delete this" is allowed. | 
| 2878         bool is_this = var->is_this(); | 2636         bool is_this = var->is_this(); | 
| 2879         DCHECK(is_sloppy(language_mode()) || is_this); | 2637         DCHECK(is_sloppy(language_mode()) || is_this); | 
| 2880         if (var->IsUnallocated()) { | 2638         if (var->IsUnallocated()) { | 
| 2881           __ LoadGlobalObject(r2); | 2639           __ LoadGlobalObject(r2); | 
| 2882           __ mov(r1, Operand(var->name())); | 2640           __ mov(r1, Operand(var->name())); | 
| 2883           __ Push(r2, r1); | 2641           __ Push(r2, r1); | 
| 2884           __ CallRuntime(Runtime::kDeleteProperty_Sloppy); | 2642           __ CallRuntime(Runtime::kDeleteProperty_Sloppy); | 
| 2885           context()->Plug(r0); | 2643           context()->Plug(r0); | 
| 2886         } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 2644         } else { | 
|  | 2645           DCHECK(!var->IsLookupSlot()); | 
|  | 2646           DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 
| 2887           // Result of deleting non-global, non-dynamic variables is false. | 2647           // Result of deleting non-global, non-dynamic variables is false. | 
| 2888           // The subexpression does not have side effects. | 2648           // The subexpression does not have side effects. | 
| 2889           context()->Plug(is_this); | 2649           context()->Plug(is_this); | 
| 2890         } else { |  | 
| 2891           // Non-global variable.  Call the runtime to try to delete from the |  | 
| 2892           // context where the variable was introduced. |  | 
| 2893           __ Push(var->name()); |  | 
| 2894           __ CallRuntime(Runtime::kDeleteLookupSlot); |  | 
| 2895           context()->Plug(r0); |  | 
| 2896         } | 2650         } | 
| 2897       } else { | 2651       } else { | 
| 2898         // Result of deleting non-property, non-variable reference is true. | 2652         // Result of deleting non-property, non-variable reference is true. | 
| 2899         // The subexpression may have side effects. | 2653         // The subexpression may have side effects. | 
| 2900         VisitForEffect(expr->expression()); | 2654         VisitForEffect(expr->expression()); | 
| 2901         context()->Plug(true); | 2655         context()->Plug(true); | 
| 2902       } | 2656       } | 
| 2903       break; | 2657       break; | 
| 2904     } | 2658     } | 
| 2905 | 2659 | 
| (...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3645   DCHECK(interrupt_address == | 3399   DCHECK(interrupt_address == | 
| 3646          isolate->builtins()->OnStackReplacement()->entry()); | 3400          isolate->builtins()->OnStackReplacement()->entry()); | 
| 3647   return ON_STACK_REPLACEMENT; | 3401   return ON_STACK_REPLACEMENT; | 
| 3648 } | 3402 } | 
| 3649 | 3403 | 
| 3650 | 3404 | 
| 3651 }  // namespace internal | 3405 }  // namespace internal | 
| 3652 }  // namespace v8 | 3406 }  // namespace v8 | 
| 3653 | 3407 | 
| 3654 #endif  // V8_TARGET_ARCH_ARM | 3408 #endif  // V8_TARGET_ARCH_ARM | 
| OLD | NEW | 
|---|