| OLD | NEW | 
|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 //     * Redistributions of source code must retain the above copyright | 6 //     * Redistributions of source code must retain the above copyright | 
| 7 //       notice, this list of conditions and the following disclaimer. | 7 //       notice, this list of conditions and the following disclaimer. | 
| 8 //     * Redistributions in binary form must reproduce the above | 8 //     * Redistributions in binary form must reproduce the above | 
| 9 //       copyright notice, this list of conditions and the following | 9 //       copyright notice, this list of conditions and the following | 
| 10 //       disclaimer in the documentation and/or other materials provided | 10 //       disclaimer in the documentation and/or other materials provided | 
| (...skipping 1169 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1180   // 2. Get the function to call (passed as receiver) from the stack, check | 1180   // 2. Get the function to call (passed as receiver) from the stack, check | 
| 1181   //    if it is a function. | 1181   //    if it is a function. | 
| 1182   // r0: actual number of arguments | 1182   // r0: actual number of arguments | 
| 1183   Label non_function; | 1183   Label non_function; | 
| 1184   __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); | 1184   __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); | 
| 1185   __ tst(r1, Operand(kSmiTagMask)); | 1185   __ tst(r1, Operand(kSmiTagMask)); | 
| 1186   __ b(eq, &non_function); | 1186   __ b(eq, &non_function); | 
| 1187   __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1187   __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 
| 1188   __ b(ne, &non_function); | 1188   __ b(ne, &non_function); | 
| 1189 | 1189 | 
| 1190   // 3a. Patch the first argument if necessary when calling a function. |  | 
| 1191   // r0: actual number of arguments | 1190   // r0: actual number of arguments | 
| 1192   // r1: function | 1191   // r1: function | 
|  | 1192   // Change context eagerly in case we need the global receiver. | 
|  | 1193   __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 
|  | 1194 | 
| 1193   Label shift_arguments; | 1195   Label shift_arguments; | 
| 1194   { Label convert_to_object, use_global_receiver, patch_receiver; | 1196   __ jmp(&shift_arguments); | 
| 1195     // Change context eagerly in case we need the global receiver. |  | 
| 1196     __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |  | 
| 1197 | 1197 | 
| 1198     __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); | 1198   // 3. Patch the first argument when calling a non-function.  The | 
| 1199     __ ldr(r2, MemOperand(r2, -kPointerSize)); | 1199   //    CALL_NON_FUNCTION builtin expects the non-function callee as | 
| 1200     // r0: actual number of arguments | 1200   //    receiver, so overwrite the first argument which will ultimately | 
| 1201     // r1: function | 1201   //    become the receiver. | 
| 1202     // r2: first argument |  | 
| 1203     __ tst(r2, Operand(kSmiTagMask)); |  | 
| 1204     __ b(eq, &convert_to_object); |  | 
| 1205 |  | 
| 1206     __ LoadRoot(r3, Heap::kNullValueRootIndex); |  | 
| 1207     __ cmp(r2, r3); |  | 
| 1208     __ b(eq, &use_global_receiver); |  | 
| 1209     __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); |  | 
| 1210     __ cmp(r2, r3); |  | 
| 1211     __ b(eq, &use_global_receiver); |  | 
| 1212 |  | 
| 1213     __ CompareObjectType(r2, r3, r3, FIRST_JS_OBJECT_TYPE); |  | 
| 1214     __ b(lt, &convert_to_object); |  | 
| 1215     __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE)); |  | 
| 1216     __ b(le, &shift_arguments); |  | 
| 1217 |  | 
| 1218     __ bind(&convert_to_object); |  | 
| 1219     __ EnterInternalFrame();  // In order to preserve argument count. |  | 
| 1220     __ mov(r0, Operand(r0, LSL, kSmiTagSize));  // Smi-tagged. |  | 
| 1221     __ push(r0); |  | 
| 1222 |  | 
| 1223     __ push(r2); |  | 
| 1224     __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); |  | 
| 1225     __ mov(r2, r0); |  | 
| 1226 |  | 
| 1227     __ pop(r0); |  | 
| 1228     __ mov(r0, Operand(r0, ASR, kSmiTagSize)); |  | 
| 1229     __ LeaveInternalFrame(); |  | 
| 1230     // Restore the function to r1. |  | 
| 1231     __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); |  | 
| 1232     __ jmp(&patch_receiver); |  | 
| 1233 |  | 
| 1234     // Use the global receiver object from the called function as the |  | 
| 1235     // receiver. |  | 
| 1236     __ bind(&use_global_receiver); |  | 
| 1237     const int kGlobalIndex = |  | 
| 1238         Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |  | 
| 1239     __ ldr(r2, FieldMemOperand(cp, kGlobalIndex)); |  | 
| 1240     __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset)); |  | 
| 1241     __ ldr(r2, FieldMemOperand(r2, kGlobalIndex)); |  | 
| 1242     __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); |  | 
| 1243 |  | 
| 1244     __ bind(&patch_receiver); |  | 
| 1245     __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2)); |  | 
| 1246     __ str(r2, MemOperand(r3, -kPointerSize)); |  | 
| 1247 |  | 
| 1248     __ jmp(&shift_arguments); |  | 
| 1249   } |  | 
| 1250 |  | 
| 1251   // 3b. Patch the first argument when calling a non-function.  The |  | 
| 1252   //     CALL_NON_FUNCTION builtin expects the non-function callee as |  | 
| 1253   //     receiver, so overwrite the first argument which will ultimately |  | 
| 1254   //     become the receiver. |  | 
| 1255   // r0: actual number of arguments | 1202   // r0: actual number of arguments | 
| 1256   // r1: function | 1203   // r1: function | 
| 1257   __ bind(&non_function); | 1204   __ bind(&non_function); | 
| 1258   __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); | 1205   __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); | 
| 1259   __ str(r1, MemOperand(r2, -kPointerSize)); | 1206   __ str(r1, MemOperand(r2, -kPointerSize)); | 
| 1260   // Clear r1 to indicate a non-function being called. | 1207   // Clear r1 to indicate a non-function being called. | 
| 1261   __ mov(r1, Operand(0, RelocInfo::NONE)); | 1208   __ mov(r1, Operand(0, RelocInfo::NONE)); | 
| 1262 | 1209 | 
| 1263   // 4. Shift arguments and return address one slot down on the stack | 1210   // 4. Shift arguments and return address one slot down on the stack | 
| 1264   //    (overwriting the original receiver).  Adjust argument count to make | 1211   //    (overwriting the original receiver).  Adjust argument count to make | 
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1352   // Push current limit and index. | 1299   // Push current limit and index. | 
| 1353   __ bind(&okay); | 1300   __ bind(&okay); | 
| 1354   __ push(r0);  // limit | 1301   __ push(r0);  // limit | 
| 1355   __ mov(r1, Operand(0, RelocInfo::NONE));  // initial index | 1302   __ mov(r1, Operand(0, RelocInfo::NONE));  // initial index | 
| 1356   __ push(r1); | 1303   __ push(r1); | 
| 1357 | 1304 | 
| 1358   // Change context eagerly to get the right global object if necessary. | 1305   // Change context eagerly to get the right global object if necessary. | 
| 1359   __ ldr(r0, MemOperand(fp, kFunctionOffset)); | 1306   __ ldr(r0, MemOperand(fp, kFunctionOffset)); | 
| 1360   __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset)); | 1307   __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset)); | 
| 1361 | 1308 | 
| 1362   // Compute the receiver. | 1309   // Push the receiver. | 
| 1363   Label call_to_object, use_global_receiver, push_receiver; |  | 
| 1364   __ ldr(r0, MemOperand(fp, kRecvOffset)); | 1310   __ ldr(r0, MemOperand(fp, kRecvOffset)); | 
| 1365   __ tst(r0, Operand(kSmiTagMask)); |  | 
| 1366   __ b(eq, &call_to_object); |  | 
| 1367   __ LoadRoot(r1, Heap::kNullValueRootIndex); |  | 
| 1368   __ cmp(r0, r1); |  | 
| 1369   __ b(eq, &use_global_receiver); |  | 
| 1370   __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |  | 
| 1371   __ cmp(r0, r1); |  | 
| 1372   __ b(eq, &use_global_receiver); |  | 
| 1373 |  | 
| 1374   // Check if the receiver is already a JavaScript object. |  | 
| 1375   // r0: receiver | 1311   // r0: receiver | 
| 1376   __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |  | 
| 1377   __ b(lt, &call_to_object); |  | 
| 1378   __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); |  | 
| 1379   __ b(le, &push_receiver); |  | 
| 1380 |  | 
| 1381   // Convert the receiver to a regular object. |  | 
| 1382   // r0: receiver |  | 
| 1383   __ bind(&call_to_object); |  | 
| 1384   __ push(r0); |  | 
| 1385   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); |  | 
| 1386   __ b(&push_receiver); |  | 
| 1387 |  | 
| 1388   // Use the current global receiver object as the receiver. |  | 
| 1389   __ bind(&use_global_receiver); |  | 
| 1390   const int kGlobalOffset = |  | 
| 1391       Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |  | 
| 1392   __ ldr(r0, FieldMemOperand(cp, kGlobalOffset)); |  | 
| 1393   __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); |  | 
| 1394   __ ldr(r0, FieldMemOperand(r0, kGlobalOffset)); |  | 
| 1395   __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |  | 
| 1396 |  | 
| 1397   // Push the receiver. |  | 
| 1398   // r0: receiver |  | 
| 1399   __ bind(&push_receiver); |  | 
| 1400   __ push(r0); | 1312   __ push(r0); | 
| 1401 | 1313 | 
| 1402   // Copy all arguments from the array to the stack. | 1314   // Copy all arguments from the array to the stack. | 
| 1403   Label entry, loop; | 1315   Label entry, loop; | 
| 1404   __ ldr(r0, MemOperand(fp, kIndexOffset)); | 1316   __ ldr(r0, MemOperand(fp, kIndexOffset)); | 
| 1405   __ b(&entry); | 1317   __ b(&entry); | 
| 1406 | 1318 | 
| 1407   // Load the current argument from the arguments array and push it to the | 1319   // Load the current argument from the arguments array and push it to the | 
| 1408   // stack. | 1320   // stack. | 
| 1409   // r0: current argument index | 1321   // r0: current argument index | 
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1565   __ bind(&dont_adapt_arguments); | 1477   __ bind(&dont_adapt_arguments); | 
| 1566   __ Jump(r3); | 1478   __ Jump(r3); | 
| 1567 } | 1479 } | 
| 1568 | 1480 | 
| 1569 | 1481 | 
| 1570 #undef __ | 1482 #undef __ | 
| 1571 | 1483 | 
| 1572 } }  // namespace v8::internal | 1484 } }  // namespace v8::internal | 
| 1573 | 1485 | 
| 1574 #endif  // V8_TARGET_ARCH_ARM | 1486 #endif  // V8_TARGET_ARCH_ARM | 
| OLD | NEW | 
|---|