OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1193 __ Branch(&done, ne, a0, Operand(zero_reg)); | 1193 __ Branch(&done, ne, a0, Operand(zero_reg)); |
1194 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); | 1194 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); |
1195 __ push(t2); | 1195 __ push(t2); |
1196 __ Addu(a0, a0, Operand(1)); | 1196 __ Addu(a0, a0, Operand(1)); |
1197 __ bind(&done); | 1197 __ bind(&done); |
1198 } | 1198 } |
1199 | 1199 |
1200 // 2. Get the function to call (passed as receiver) from the stack, check | 1200 // 2. Get the function to call (passed as receiver) from the stack, check |
1201 // if it is a function. | 1201 // if it is a function. |
1202 // a0: actual number of arguments | 1202 // a0: actual number of arguments |
1203 Label non_function; | 1203 Label slow, non_function; |
1204 __ sll(at, a0, kPointerSizeLog2); | 1204 __ sll(at, a0, kPointerSizeLog2); |
1205 __ addu(at, sp, at); | 1205 __ addu(at, sp, at); |
1206 __ lw(a1, MemOperand(at)); | 1206 __ lw(a1, MemOperand(at)); |
1207 __ And(at, a1, Operand(kSmiTagMask)); | 1207 __ And(at, a1, Operand(kSmiTagMask)); |
1208 __ Branch(&non_function, eq, at, Operand(zero_reg)); | 1208 __ Branch(&non_function, eq, at, Operand(zero_reg)); |
1209 __ GetObjectType(a1, a2, a2); | 1209 __ GetObjectType(a1, a2, a2); |
1210 __ Branch(&non_function, ne, a2, Operand(JS_FUNCTION_TYPE)); | 1210 __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE)); |
1211 | 1211 |
1212 // 3a. Patch the first argument if necessary when calling a function. | 1212 // 3a. Patch the first argument if necessary when calling a function. |
1213 // a0: actual number of arguments | 1213 // a0: actual number of arguments |
1214 // a1: function | 1214 // a1: function |
1215 Label shift_arguments; | 1215 Label shift_arguments; |
| 1216 __ li(t0, Operand(0, RelocInfo::NONE)); // Indicate regular JS_FUNCTION. |
1216 { Label convert_to_object, use_global_receiver, patch_receiver; | 1217 { Label convert_to_object, use_global_receiver, patch_receiver; |
1217 // Change context eagerly in case we need the global receiver. | 1218 // Change context eagerly in case we need the global receiver. |
1218 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 1219 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
1219 | 1220 |
1220 // Do not transform the receiver for strict mode functions. | 1221 // Do not transform the receiver for strict mode functions. |
1221 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 1222 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
1222 __ lw(a3, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset)); | 1223 __ lw(a3, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset)); |
1223 __ And(t0, a3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + | 1224 __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + |
1224 kSmiTagSize))); | 1225 kSmiTagSize))); |
1225 __ Branch(&shift_arguments, ne, t0, Operand(zero_reg)); | 1226 __ Branch(&shift_arguments, ne, t3, Operand(zero_reg)); |
1226 | 1227 |
1227 // Do not transform the receiver for native (Compilerhints already in a3). | 1228 // Do not transform the receiver for native (Compilerhints already in a3). |
1228 __ And(t0, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); | 1229 __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); |
1229 __ Branch(&shift_arguments, ne, t0, Operand(zero_reg)); | 1230 __ Branch(&shift_arguments, ne, t3, Operand(zero_reg)); |
1230 | 1231 |
1231 // Compute the receiver in non-strict mode. | 1232 // Compute the receiver in non-strict mode. |
1232 // Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2). | 1233 // Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2). |
1233 __ sll(at, a0, kPointerSizeLog2); | 1234 __ sll(at, a0, kPointerSizeLog2); |
1234 __ addu(a2, sp, at); | 1235 __ addu(a2, sp, at); |
1235 __ lw(a2, MemOperand(a2, -kPointerSize)); | 1236 __ lw(a2, MemOperand(a2, -kPointerSize)); |
1236 // a0: actual number of arguments | 1237 // a0: actual number of arguments |
1237 // a1: function | 1238 // a1: function |
1238 // a2: first argument | 1239 // a2: first argument |
1239 __ JumpIfSmi(a2, &convert_to_object, t2); | 1240 __ JumpIfSmi(a2, &convert_to_object, t2); |
(...skipping 15 matching lines...) Expand all Loading... |
1255 __ push(a0); | 1256 __ push(a0); |
1256 | 1257 |
1257 __ push(a2); | 1258 __ push(a2); |
1258 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 1259 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
1259 __ mov(a2, v0); | 1260 __ mov(a2, v0); |
1260 | 1261 |
1261 __ pop(a0); | 1262 __ pop(a0); |
1262 __ sra(a0, a0, kSmiTagSize); // Un-tag. | 1263 __ sra(a0, a0, kSmiTagSize); // Un-tag. |
1263 // Leave internal frame. | 1264 // Leave internal frame. |
1264 } | 1265 } |
1265 // Restore the function to a1. | 1266 // Restore the function to a1, and the flag to t0. |
1266 __ sll(at, a0, kPointerSizeLog2); | 1267 __ sll(at, a0, kPointerSizeLog2); |
1267 __ addu(at, sp, at); | 1268 __ addu(at, sp, at); |
1268 __ lw(a1, MemOperand(at)); | 1269 __ lw(a1, MemOperand(at)); |
| 1270 __ li(t0, Operand(0, RelocInfo::NONE)); |
1269 __ Branch(&patch_receiver); | 1271 __ Branch(&patch_receiver); |
1270 | 1272 |
1271 // Use the global receiver object from the called function as the | 1273 // Use the global receiver object from the called function as the |
1272 // receiver. | 1274 // receiver. |
1273 __ bind(&use_global_receiver); | 1275 __ bind(&use_global_receiver); |
1274 const int kGlobalIndex = | 1276 const int kGlobalIndex = |
1275 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 1277 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
1276 __ lw(a2, FieldMemOperand(cp, kGlobalIndex)); | 1278 __ lw(a2, FieldMemOperand(cp, kGlobalIndex)); |
1277 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalContextOffset)); | 1279 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalContextOffset)); |
1278 __ lw(a2, FieldMemOperand(a2, kGlobalIndex)); | 1280 __ lw(a2, FieldMemOperand(a2, kGlobalIndex)); |
1279 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); | 1281 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); |
1280 | 1282 |
1281 __ bind(&patch_receiver); | 1283 __ bind(&patch_receiver); |
1282 __ sll(at, a0, kPointerSizeLog2); | 1284 __ sll(at, a0, kPointerSizeLog2); |
1283 __ addu(a3, sp, at); | 1285 __ addu(a3, sp, at); |
1284 __ sw(a2, MemOperand(a3, -kPointerSize)); | 1286 __ sw(a2, MemOperand(a3, -kPointerSize)); |
1285 | 1287 |
1286 __ Branch(&shift_arguments); | 1288 __ Branch(&shift_arguments); |
1287 } | 1289 } |
1288 | 1290 |
1289 // 3b. Patch the first argument when calling a non-function. The | 1291 // 3b. Check for function proxy. |
| 1292 __ bind(&slow); |
| 1293 __ li(t0, Operand(1, RelocInfo::NONE)); // Indicate function proxy. |
| 1294 __ Branch(&shift_arguments, eq, a2, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 1295 |
| 1296 __ bind(&non_function); |
| 1297 __ li(t0, Operand(2, RelocInfo::NONE)); // Indicate non-function. |
| 1298 |
| 1299 // 3c. Patch the first argument when calling a non-function. The |
1290 // CALL_NON_FUNCTION builtin expects the non-function callee as | 1300 // CALL_NON_FUNCTION builtin expects the non-function callee as |
1291 // receiver, so overwrite the first argument which will ultimately | 1301 // receiver, so overwrite the first argument which will ultimately |
1292 // become the receiver. | 1302 // become the receiver. |
1293 // a0: actual number of arguments | 1303 // a0: actual number of arguments |
1294 // a1: function | 1304 // a1: function |
1295 __ bind(&non_function); | 1305 // t0: call type (0: JS function, 1: function proxy, 2: non-function) |
1296 // Restore the function in case it has been modified. | |
1297 __ sll(at, a0, kPointerSizeLog2); | 1306 __ sll(at, a0, kPointerSizeLog2); |
1298 __ addu(a2, sp, at); | 1307 __ addu(a2, sp, at); |
1299 __ sw(a1, MemOperand(a2, -kPointerSize)); | 1308 __ sw(a1, MemOperand(a2, -kPointerSize)); |
1300 // Clear a1 to indicate a non-function being called. | |
1301 __ mov(a1, zero_reg); | |
1302 | 1309 |
1303 // 4. Shift arguments and return address one slot down on the stack | 1310 // 4. Shift arguments and return address one slot down on the stack |
1304 // (overwriting the original receiver). Adjust argument count to make | 1311 // (overwriting the original receiver). Adjust argument count to make |
1305 // the original first argument the new receiver. | 1312 // the original first argument the new receiver. |
1306 // a0: actual number of arguments | 1313 // a0: actual number of arguments |
1307 // a1: function | 1314 // a1: function |
| 1315 // t0: call type (0: JS function, 1: function proxy, 2: non-function) |
1308 __ bind(&shift_arguments); | 1316 __ bind(&shift_arguments); |
1309 { Label loop; | 1317 { Label loop; |
1310 // Calculate the copy start address (destination). Copy end address is sp. | 1318 // Calculate the copy start address (destination). Copy end address is sp. |
1311 __ sll(at, a0, kPointerSizeLog2); | 1319 __ sll(at, a0, kPointerSizeLog2); |
1312 __ addu(a2, sp, at); | 1320 __ addu(a2, sp, at); |
1313 | 1321 |
1314 __ bind(&loop); | 1322 __ bind(&loop); |
1315 __ lw(at, MemOperand(a2, -kPointerSize)); | 1323 __ lw(at, MemOperand(a2, -kPointerSize)); |
1316 __ sw(at, MemOperand(a2)); | 1324 __ sw(at, MemOperand(a2)); |
1317 __ Subu(a2, a2, Operand(kPointerSize)); | 1325 __ Subu(a2, a2, Operand(kPointerSize)); |
1318 __ Branch(&loop, ne, a2, Operand(sp)); | 1326 __ Branch(&loop, ne, a2, Operand(sp)); |
1319 // Adjust the actual number of arguments and remove the top element | 1327 // Adjust the actual number of arguments and remove the top element |
1320 // (which is a copy of the last argument). | 1328 // (which is a copy of the last argument). |
1321 __ Subu(a0, a0, Operand(1)); | 1329 __ Subu(a0, a0, Operand(1)); |
1322 __ Pop(); | 1330 __ Pop(); |
1323 } | 1331 } |
1324 | 1332 |
1325 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin. | 1333 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, |
| 1334 // or a function proxy via CALL_FUNCTION_PROXY. |
1326 // a0: actual number of arguments | 1335 // a0: actual number of arguments |
1327 // a1: function | 1336 // a1: function |
1328 { Label function; | 1337 // t0: call type (0: JS function, 1: function proxy, 2: non-function) |
1329 __ Branch(&function, ne, a1, Operand(zero_reg)); | 1338 { Label function, non_proxy; |
1330 __ mov(a2, zero_reg); // expected arguments is 0 for CALL_NON_FUNCTION | 1339 __ Branch(&function, eq, t0, Operand(zero_reg)); |
| 1340 // Expected number of arguments is 0 for CALL_NON_FUNCTION. |
| 1341 __ mov(a2, zero_reg); |
| 1342 __ SetCallKind(t1, CALL_AS_METHOD); |
| 1343 __ Branch(&non_proxy, ne, t0, Operand(1)); |
| 1344 |
| 1345 __ push(a1); // Re-add proxy object as additional argument. |
| 1346 __ Addu(a0, a0, Operand(1)); |
| 1347 __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY); |
| 1348 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 1349 RelocInfo::CODE_TARGET); |
| 1350 |
| 1351 __ bind(&non_proxy); |
1331 __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); | 1352 __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); |
1332 __ SetCallKind(t1, CALL_AS_METHOD); | |
1333 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1353 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1334 RelocInfo::CODE_TARGET); | 1354 RelocInfo::CODE_TARGET); |
1335 __ bind(&function); | 1355 __ bind(&function); |
1336 } | 1356 } |
1337 | 1357 |
1338 // 5b. Get the code to call from the function and check that the number of | 1358 // 5b. Get the code to call from the function and check that the number of |
1339 // expected arguments matches what we're providing. If so, jump | 1359 // expected arguments matches what we're providing. If so, jump |
1340 // (tail-call) to the code in register edx without checking arguments. | 1360 // (tail-call) to the code in register edx without checking arguments. |
1341 // a0: actual number of arguments | 1361 // a0: actual number of arguments |
1342 // a1: function | 1362 // a1: function |
(...skipping 14 matching lines...) Expand all Loading... |
1357 | 1377 |
1358 | 1378 |
1359 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1379 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
1360 const int kIndexOffset = -5 * kPointerSize; | 1380 const int kIndexOffset = -5 * kPointerSize; |
1361 const int kLimitOffset = -4 * kPointerSize; | 1381 const int kLimitOffset = -4 * kPointerSize; |
1362 const int kArgsOffset = 2 * kPointerSize; | 1382 const int kArgsOffset = 2 * kPointerSize; |
1363 const int kRecvOffset = 3 * kPointerSize; | 1383 const int kRecvOffset = 3 * kPointerSize; |
1364 const int kFunctionOffset = 4 * kPointerSize; | 1384 const int kFunctionOffset = 4 * kPointerSize; |
1365 | 1385 |
1366 { | 1386 { |
1367 FrameScope scope(masm, StackFrame::INTERNAL); | 1387 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
1368 | |
1369 __ lw(a0, MemOperand(fp, kFunctionOffset)); // Get the function. | 1388 __ lw(a0, MemOperand(fp, kFunctionOffset)); // Get the function. |
1370 __ push(a0); | 1389 __ push(a0); |
1371 __ lw(a0, MemOperand(fp, kArgsOffset)); // Get the args array. | 1390 __ lw(a0, MemOperand(fp, kArgsOffset)); // Get the args array. |
1372 __ push(a0); | 1391 __ push(a0); |
1373 // Returns (in v0) number of arguments to copy to stack as Smi. | 1392 // Returns (in v0) number of arguments to copy to stack as Smi. |
1374 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 1393 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
1375 | 1394 |
1376 // Check the stack for overflow. We are not trying need to catch | 1395 // Check the stack for overflow. We are not trying to catch |
1377 // interruptions (e.g. debug break and preemption) here, so the "real stack | 1396 // interruptions (e.g. debug break and preemption) here, so the "real stack |
1378 // limit" is checked. | 1397 // limit" is checked. |
1379 Label okay; | 1398 Label okay; |
1380 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); | 1399 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); |
1381 // Make a2 the space we have left. The stack might already be overflowed | 1400 // Make a2 the space we have left. The stack might already be overflowed |
1382 // here which will cause a2 to become negative. | 1401 // here which will cause a2 to become negative. |
1383 __ subu(a2, sp, a2); | 1402 __ subu(a2, sp, a2); |
1384 // Check if the arguments will overflow the stack. | 1403 // Check if the arguments will overflow the stack. |
1385 __ sll(t0, v0, kPointerSizeLog2 - kSmiTagSize); | 1404 __ sll(t3, v0, kPointerSizeLog2 - kSmiTagSize); |
1386 __ Branch(&okay, gt, a2, Operand(t0)); // Signed comparison. | 1405 __ Branch(&okay, gt, a2, Operand(t3)); // Signed comparison. |
1387 | 1406 |
1388 // Out of stack space. | 1407 // Out of stack space. |
1389 __ lw(a1, MemOperand(fp, kFunctionOffset)); | 1408 __ lw(a1, MemOperand(fp, kFunctionOffset)); |
1390 __ push(a1); | 1409 __ push(a1); |
1391 __ push(v0); | 1410 __ push(v0); |
1392 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); | 1411 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); |
1393 // End of stack check. | 1412 // End of stack check. |
1394 | 1413 |
1395 // Push current limit and index. | 1414 // Push current limit and index. |
1396 __ bind(&okay); | 1415 __ bind(&okay); |
1397 __ push(v0); // Limit. | 1416 __ push(v0); // Limit. |
1398 __ mov(a1, zero_reg); // Initial index. | 1417 __ mov(a1, zero_reg); // Initial index. |
1399 __ push(a1); | 1418 __ push(a1); |
1400 | 1419 |
| 1420 // Get the receiver. |
| 1421 __ lw(a0, MemOperand(fp, kRecvOffset)); |
| 1422 |
| 1423 // Check that the function is a JS function (otherwise it must be a proxy). |
| 1424 Label push_receiver; |
| 1425 __ lw(a1, MemOperand(fp, kFunctionOffset)); |
| 1426 __ GetObjectType(a1, a2, a2); |
| 1427 __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE)); |
| 1428 |
1401 // Change context eagerly to get the right global object if necessary. | 1429 // Change context eagerly to get the right global object if necessary. |
1402 __ lw(a0, MemOperand(fp, kFunctionOffset)); | 1430 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
1403 __ lw(cp, FieldMemOperand(a0, JSFunction::kContextOffset)); | 1431 // Load the shared function info while the function is still in a1. |
1404 // Load the shared function info while the function is still in a0. | 1432 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
1405 __ lw(a1, FieldMemOperand(a0, JSFunction::kSharedFunctionInfoOffset)); | |
1406 | 1433 |
1407 // Compute the receiver. | 1434 // Compute the receiver. |
1408 Label call_to_object, use_global_receiver, push_receiver; | |
1409 __ lw(a0, MemOperand(fp, kRecvOffset)); | |
1410 | |
1411 // Do not transform the receiver for strict mode functions. | 1435 // Do not transform the receiver for strict mode functions. |
1412 __ lw(a2, FieldMemOperand(a1, SharedFunctionInfo::kCompilerHintsOffset)); | 1436 Label call_to_object, use_global_receiver; |
1413 __ And(t0, a2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + | 1437 __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset)); |
| 1438 __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + |
1414 kSmiTagSize))); | 1439 kSmiTagSize))); |
1415 __ Branch(&push_receiver, ne, t0, Operand(zero_reg)); | 1440 __ Branch(&push_receiver, ne, t3, Operand(zero_reg)); |
1416 | 1441 |
1417 // Do not transform the receiver for native (Compilerhints already in a2). | 1442 // Do not transform the receiver for native (Compilerhints already in a2). |
1418 __ And(t0, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); | 1443 __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); |
1419 __ Branch(&push_receiver, ne, t0, Operand(zero_reg)); | 1444 __ Branch(&push_receiver, ne, t3, Operand(zero_reg)); |
1420 | 1445 |
1421 // Compute the receiver in non-strict mode. | 1446 // Compute the receiver in non-strict mode. |
1422 __ And(t0, a0, Operand(kSmiTagMask)); | 1447 __ And(t3, a0, Operand(kSmiTagMask)); |
1423 __ Branch(&call_to_object, eq, t0, Operand(zero_reg)); | 1448 __ Branch(&call_to_object, eq, t3, Operand(zero_reg)); |
1424 __ LoadRoot(a1, Heap::kNullValueRootIndex); | 1449 __ LoadRoot(a1, Heap::kNullValueRootIndex); |
1425 __ Branch(&use_global_receiver, eq, a0, Operand(a1)); | 1450 __ Branch(&use_global_receiver, eq, a0, Operand(a1)); |
1426 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); | 1451 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); |
1427 __ Branch(&use_global_receiver, eq, a0, Operand(a2)); | 1452 __ Branch(&use_global_receiver, eq, a0, Operand(a2)); |
1428 | 1453 |
1429 // Check if the receiver is already a JavaScript object. | 1454 // Check if the receiver is already a JavaScript object. |
1430 // a0: receiver | 1455 // a0: receiver |
1431 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 1456 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
1432 __ GetObjectType(a0, a1, a1); | 1457 __ GetObjectType(a0, a1, a1); |
1433 __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); | 1458 __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1474 // Use inline caching to access the arguments. | 1499 // Use inline caching to access the arguments. |
1475 __ lw(a0, MemOperand(fp, kIndexOffset)); | 1500 __ lw(a0, MemOperand(fp, kIndexOffset)); |
1476 __ Addu(a0, a0, Operand(1 << kSmiTagSize)); | 1501 __ Addu(a0, a0, Operand(1 << kSmiTagSize)); |
1477 __ sw(a0, MemOperand(fp, kIndexOffset)); | 1502 __ sw(a0, MemOperand(fp, kIndexOffset)); |
1478 | 1503 |
1479 // Test if the copy loop has finished copying all the elements from the | 1504 // Test if the copy loop has finished copying all the elements from the |
1480 // arguments object. | 1505 // arguments object. |
1481 __ bind(&entry); | 1506 __ bind(&entry); |
1482 __ lw(a1, MemOperand(fp, kLimitOffset)); | 1507 __ lw(a1, MemOperand(fp, kLimitOffset)); |
1483 __ Branch(&loop, ne, a0, Operand(a1)); | 1508 __ Branch(&loop, ne, a0, Operand(a1)); |
| 1509 |
1484 // Invoke the function. | 1510 // Invoke the function. |
| 1511 Label call_proxy; |
1485 ParameterCount actual(a0); | 1512 ParameterCount actual(a0); |
1486 __ sra(a0, a0, kSmiTagSize); | 1513 __ sra(a0, a0, kSmiTagSize); |
1487 __ lw(a1, MemOperand(fp, kFunctionOffset)); | 1514 __ lw(a1, MemOperand(fp, kFunctionOffset)); |
| 1515 __ GetObjectType(a1, a2, a2); |
| 1516 __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE)); |
| 1517 |
1488 __ InvokeFunction(a1, actual, CALL_FUNCTION, | 1518 __ InvokeFunction(a1, actual, CALL_FUNCTION, |
1489 NullCallWrapper(), CALL_AS_METHOD); | 1519 NullCallWrapper(), CALL_AS_METHOD); |
1490 | 1520 |
| 1521 frame_scope.GenerateLeaveFrame(); |
| 1522 __ Ret(USE_DELAY_SLOT); |
| 1523 __ Addu(sp, sp, Operand(3 * kPointerSize)); // In delay slot. |
| 1524 |
| 1525 // Invoke the function proxy. |
| 1526 __ bind(&call_proxy); |
| 1527 __ push(a1); // Add function proxy as last argument. |
| 1528 __ Addu(a0, a0, Operand(1)); |
| 1529 __ li(a2, Operand(0, RelocInfo::NONE)); |
| 1530 __ SetCallKind(t1, CALL_AS_METHOD); |
| 1531 __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY); |
| 1532 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 1533 RelocInfo::CODE_TARGET); |
| 1534 |
1491 // Tear down the internal frame and remove function, receiver and args. | 1535 // Tear down the internal frame and remove function, receiver and args. |
1492 } | 1536 } |
1493 __ Addu(sp, sp, Operand(3 * kPointerSize)); | 1537 |
1494 __ Ret(); | 1538 __ Ret(USE_DELAY_SLOT); |
| 1539 __ Addu(sp, sp, Operand(3 * kPointerSize)); // In delay slot. |
1495 } | 1540 } |
1496 | 1541 |
1497 | 1542 |
1498 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { | 1543 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { |
1499 __ sll(a0, a0, kSmiTagSize); | 1544 __ sll(a0, a0, kSmiTagSize); |
1500 __ li(t0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1545 __ li(t0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
1501 __ MultiPush(a0.bit() | a1.bit() | t0.bit() | fp.bit() | ra.bit()); | 1546 __ MultiPush(a0.bit() | a1.bit() | t0.bit() | fp.bit() | ra.bit()); |
1502 __ Addu(fp, sp, Operand(3 * kPointerSize)); | 1547 __ Addu(fp, sp, Operand(3 * kPointerSize)); |
1503 } | 1548 } |
1504 | 1549 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1632 __ bind(&dont_adapt_arguments); | 1677 __ bind(&dont_adapt_arguments); |
1633 __ Jump(a3); | 1678 __ Jump(a3); |
1634 } | 1679 } |
1635 | 1680 |
1636 | 1681 |
1637 #undef __ | 1682 #undef __ |
1638 | 1683 |
1639 } } // namespace v8::internal | 1684 } } // namespace v8::internal |
1640 | 1685 |
1641 #endif // V8_TARGET_ARCH_MIPS | 1686 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |