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_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 1234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 __ CallRuntime(Runtime::kStackGuard, 0); | 1245 __ CallRuntime(Runtime::kStackGuard, 0); |
1246 } | 1246 } |
1247 __ Jump(masm->isolate()->builtins()->OnStackReplacement(), | 1247 __ Jump(masm->isolate()->builtins()->OnStackReplacement(), |
1248 RelocInfo::CODE_TARGET); | 1248 RelocInfo::CODE_TARGET); |
1249 | 1249 |
1250 __ bind(&ok); | 1250 __ bind(&ok); |
1251 __ Ret(); | 1251 __ Ret(); |
1252 } | 1252 } |
1253 | 1253 |
1254 | 1254 |
| 1255 // static |
1255 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { | 1256 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { |
1256 // 1. Make sure we have at least one argument. | 1257 // 1. Make sure we have at least one argument. |
1257 // a0: actual number of arguments | 1258 // a0: actual number of arguments |
1258 { Label done; | 1259 { |
| 1260 Label done; |
1259 __ Branch(&done, ne, a0, Operand(zero_reg)); | 1261 __ Branch(&done, ne, a0, Operand(zero_reg)); |
1260 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); | 1262 __ PushRoot(Heap::kUndefinedValueRootIndex); |
1261 __ push(t2); | |
1262 __ Addu(a0, a0, Operand(1)); | 1263 __ Addu(a0, a0, Operand(1)); |
1263 __ bind(&done); | 1264 __ bind(&done); |
1264 } | 1265 } |
1265 | 1266 |
1266 // 2. Get the function to call (passed as receiver) from the stack, check | 1267 // 2. Get the function to call (passed as receiver) from the stack. |
1267 // if it is a function. | |
1268 // a0: actual number of arguments | 1268 // a0: actual number of arguments |
1269 Label slow, non_function; | |
1270 __ sll(at, a0, kPointerSizeLog2); | 1269 __ sll(at, a0, kPointerSizeLog2); |
1271 __ addu(at, sp, at); | 1270 __ addu(at, sp, at); |
1272 __ lw(a1, MemOperand(at)); | 1271 __ lw(a1, MemOperand(at)); |
1273 __ JumpIfSmi(a1, &non_function); | |
1274 __ GetObjectType(a1, a2, a2); | |
1275 __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE)); | |
1276 | 1272 |
1277 // 3a. Patch the first argument if necessary when calling a function. | 1273 // 3. Shift arguments and return address one slot down on the stack |
1278 // a0: actual number of arguments | |
1279 // a1: function | |
1280 Label shift_arguments; | |
1281 __ li(t0, Operand(0, RelocInfo::NONE32)); // Indicate regular JS_FUNCTION. | |
1282 { Label convert_to_object, use_global_proxy, patch_receiver; | |
1283 // Change context eagerly in case we need the global receiver. | |
1284 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | |
1285 | |
1286 // Do not transform the receiver for strict mode functions. | |
1287 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | |
1288 __ lw(a3, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset)); | |
1289 __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + | |
1290 kSmiTagSize))); | |
1291 __ Branch(&shift_arguments, ne, t3, Operand(zero_reg)); | |
1292 | |
1293 // Do not transform the receiver for native (Compilerhints already in a3). | |
1294 __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); | |
1295 __ Branch(&shift_arguments, ne, t3, Operand(zero_reg)); | |
1296 | |
1297 // Compute the receiver in sloppy mode. | |
1298 // Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2). | |
1299 __ sll(at, a0, kPointerSizeLog2); | |
1300 __ addu(a2, sp, at); | |
1301 __ lw(a2, MemOperand(a2, -kPointerSize)); | |
1302 // a0: actual number of arguments | |
1303 // a1: function | |
1304 // a2: first argument | |
1305 __ JumpIfSmi(a2, &convert_to_object, t2); | |
1306 | |
1307 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex); | |
1308 __ Branch(&use_global_proxy, eq, a2, Operand(a3)); | |
1309 __ LoadRoot(a3, Heap::kNullValueRootIndex); | |
1310 __ Branch(&use_global_proxy, eq, a2, Operand(a3)); | |
1311 | |
1312 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | |
1313 __ GetObjectType(a2, a3, a3); | |
1314 __ Branch(&shift_arguments, ge, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); | |
1315 | |
1316 __ bind(&convert_to_object); | |
1317 // Enter an internal frame in order to preserve argument count. | |
1318 { | |
1319 FrameScope scope(masm, StackFrame::INTERNAL); | |
1320 __ sll(a0, a0, kSmiTagSize); // Smi tagged. | |
1321 __ push(a0); | |
1322 __ mov(a0, a2); | |
1323 ToObjectStub stub(masm->isolate()); | |
1324 __ CallStub(&stub); | |
1325 __ mov(a2, v0); | |
1326 | |
1327 __ pop(a0); | |
1328 __ sra(a0, a0, kSmiTagSize); // Un-tag. | |
1329 // Leave internal frame. | |
1330 } | |
1331 | |
1332 // Restore the function to a1, and the flag to t0. | |
1333 __ sll(at, a0, kPointerSizeLog2); | |
1334 __ addu(at, sp, at); | |
1335 __ lw(a1, MemOperand(at)); | |
1336 __ Branch(USE_DELAY_SLOT, &patch_receiver); | |
1337 __ li(t0, Operand(0, RelocInfo::NONE32)); // In delay slot. | |
1338 | |
1339 __ bind(&use_global_proxy); | |
1340 __ lw(a2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | |
1341 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset)); | |
1342 | |
1343 __ bind(&patch_receiver); | |
1344 __ sll(at, a0, kPointerSizeLog2); | |
1345 __ addu(a3, sp, at); | |
1346 __ sw(a2, MemOperand(a3, -kPointerSize)); | |
1347 | |
1348 __ Branch(&shift_arguments); | |
1349 } | |
1350 | |
1351 // 3b. Check for function proxy. | |
1352 __ bind(&slow); | |
1353 __ li(t0, Operand(1, RelocInfo::NONE32)); // Indicate function proxy. | |
1354 __ Branch(&shift_arguments, eq, a2, Operand(JS_FUNCTION_PROXY_TYPE)); | |
1355 | |
1356 __ bind(&non_function); | |
1357 __ li(t0, Operand(2, RelocInfo::NONE32)); // Indicate non-function. | |
1358 | |
1359 // 3c. Patch the first argument when calling a non-function. The | |
1360 // CALL_NON_FUNCTION builtin expects the non-function callee as | |
1361 // receiver, so overwrite the first argument which will ultimately | |
1362 // become the receiver. | |
1363 // a0: actual number of arguments | |
1364 // a1: function | |
1365 // t0: call type (0: JS function, 1: function proxy, 2: non-function) | |
1366 __ sll(at, a0, kPointerSizeLog2); | |
1367 __ addu(a2, sp, at); | |
1368 __ sw(a1, MemOperand(a2, -kPointerSize)); | |
1369 | |
1370 // 4. Shift arguments and return address one slot down on the stack | |
1371 // (overwriting the original receiver). Adjust argument count to make | 1274 // (overwriting the original receiver). Adjust argument count to make |
1372 // the original first argument the new receiver. | 1275 // the original first argument the new receiver. |
1373 // a0: actual number of arguments | 1276 // a0: actual number of arguments |
1374 // a1: function | 1277 // a1: function |
1375 // t0: call type (0: JS function, 1: function proxy, 2: non-function) | 1278 { |
1376 __ bind(&shift_arguments); | 1279 Label loop; |
1377 { Label loop; | |
1378 // Calculate the copy start address (destination). Copy end address is sp. | 1280 // Calculate the copy start address (destination). Copy end address is sp. |
1379 __ sll(at, a0, kPointerSizeLog2); | 1281 __ sll(at, a0, kPointerSizeLog2); |
1380 __ addu(a2, sp, at); | 1282 __ addu(a2, sp, at); |
1381 | 1283 |
1382 __ bind(&loop); | 1284 __ bind(&loop); |
1383 __ lw(at, MemOperand(a2, -kPointerSize)); | 1285 __ lw(at, MemOperand(a2, -kPointerSize)); |
1384 __ sw(at, MemOperand(a2)); | 1286 __ sw(at, MemOperand(a2)); |
1385 __ Subu(a2, a2, Operand(kPointerSize)); | 1287 __ Subu(a2, a2, Operand(kPointerSize)); |
1386 __ Branch(&loop, ne, a2, Operand(sp)); | 1288 __ Branch(&loop, ne, a2, Operand(sp)); |
1387 // Adjust the actual number of arguments and remove the top element | 1289 // Adjust the actual number of arguments and remove the top element |
1388 // (which is a copy of the last argument). | 1290 // (which is a copy of the last argument). |
1389 __ Subu(a0, a0, Operand(1)); | 1291 __ Subu(a0, a0, Operand(1)); |
1390 __ Pop(); | 1292 __ Pop(); |
1391 } | 1293 } |
1392 | 1294 |
1393 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, | 1295 // 4. Call the callable. |
1394 // or a function proxy via CALL_FUNCTION_PROXY. | 1296 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1395 // a0: actual number of arguments | |
1396 // a1: function | |
1397 // t0: call type (0: JS function, 1: function proxy, 2: non-function) | |
1398 { Label function, non_proxy; | |
1399 __ Branch(&function, eq, t0, Operand(zero_reg)); | |
1400 // Expected number of arguments is 0 for CALL_NON_FUNCTION. | |
1401 __ mov(a2, zero_reg); | |
1402 __ Branch(&non_proxy, ne, t0, Operand(1)); | |
1403 | |
1404 __ push(a1); // Re-add proxy object as additional argument. | |
1405 __ Addu(a0, a0, Operand(1)); | |
1406 __ GetBuiltinFunction(a1, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX); | |
1407 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
1408 RelocInfo::CODE_TARGET); | |
1409 | |
1410 __ bind(&non_proxy); | |
1411 __ GetBuiltinFunction(a1, Context::CALL_NON_FUNCTION_BUILTIN_INDEX); | |
1412 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
1413 RelocInfo::CODE_TARGET); | |
1414 __ bind(&function); | |
1415 } | |
1416 | |
1417 // 5b. Get the code to call from the function and check that the number of | |
1418 // expected arguments matches what we're providing. If so, jump | |
1419 // (tail-call) to the code in register edx without checking arguments. | |
1420 // a0: actual number of arguments | |
1421 // a1: function | |
1422 __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | |
1423 __ lw(a2, | |
1424 FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset)); | |
1425 __ sra(a2, a2, kSmiTagSize); | |
1426 // Check formal and actual parameter counts. | |
1427 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
1428 RelocInfo::CODE_TARGET, ne, a2, Operand(a0)); | |
1429 | |
1430 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | |
1431 ParameterCount expected(0); | |
1432 __ InvokeCode(a3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); | |
1433 } | 1297 } |
1434 | 1298 |
1435 | 1299 |
1436 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 1300 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
1437 const int argumentsOffset, | 1301 const int argumentsOffset, |
1438 const int indexOffset, | 1302 const int indexOffset, |
1439 const int limitOffset) { | 1303 const int limitOffset) { |
1440 Label entry, loop; | 1304 Label entry, loop; |
1441 Register receiver = LoadDescriptor::ReceiverRegister(); | 1305 Register receiver = LoadDescriptor::ReceiverRegister(); |
1442 Register key = LoadDescriptor::NameRegister(); | 1306 Register key = LoadDescriptor::NameRegister(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1486 const int kFormalParameters = targetIsArgument ? 3 : 2; | 1350 const int kFormalParameters = targetIsArgument ? 3 : 2; |
1487 const int kStackSize = kFormalParameters + 1; | 1351 const int kStackSize = kFormalParameters + 1; |
1488 | 1352 |
1489 { | 1353 { |
1490 FrameScope frame_scope(masm, StackFrame::INTERNAL); | 1354 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
1491 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; | 1355 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; |
1492 const int kReceiverOffset = kArgumentsOffset + kPointerSize; | 1356 const int kReceiverOffset = kArgumentsOffset + kPointerSize; |
1493 const int kFunctionOffset = kReceiverOffset + kPointerSize; | 1357 const int kFunctionOffset = kReceiverOffset + kPointerSize; |
1494 | 1358 |
1495 __ lw(a0, MemOperand(fp, kFunctionOffset)); // Get the function. | 1359 __ lw(a0, MemOperand(fp, kFunctionOffset)); // Get the function. |
1496 __ push(a0); | 1360 __ lw(a1, MemOperand(fp, kArgumentsOffset)); // Get the args array. |
1497 __ lw(a0, MemOperand(fp, kArgumentsOffset)); // Get the args array. | 1361 __ Push(a0, a1); |
1498 __ push(a0); | |
1499 // Returns (in v0) number of arguments to copy to stack as Smi. | 1362 // Returns (in v0) number of arguments to copy to stack as Smi. |
1500 if (targetIsArgument) { | 1363 if (targetIsArgument) { |
1501 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, | 1364 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, |
1502 CALL_FUNCTION); | 1365 CALL_FUNCTION); |
1503 } else { | 1366 } else { |
1504 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); | 1367 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); |
1505 } | 1368 } |
1506 | 1369 |
1507 // Returns the result in v0. | 1370 // Returns the result in v0. |
1508 Generate_CheckStackOverflow(masm, kFunctionOffset, v0, kArgcIsSmiTagged); | 1371 Generate_CheckStackOverflow(masm, kFunctionOffset, v0, kArgcIsSmiTagged); |
1509 | 1372 |
1510 // Push current limit and index. | 1373 // Push current limit and index. |
1511 const int kIndexOffset = | 1374 const int kIndexOffset = |
1512 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); | 1375 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |
1513 const int kLimitOffset = | 1376 const int kLimitOffset = |
1514 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); | 1377 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |
1515 __ mov(a1, zero_reg); | 1378 __ mov(a1, zero_reg); |
1516 __ Push(v0, a1); // Limit and initial index. | 1379 __ lw(a2, MemOperand(fp, kReceiverOffset)); |
1517 | 1380 __ Push(v0, a1, a2); // limit, initial index and receiver. |
1518 // Get the receiver. | |
1519 __ lw(a0, MemOperand(fp, kReceiverOffset)); | |
1520 | |
1521 // Check that the function is a JS function (otherwise it must be a proxy). | |
1522 Label push_receiver; | |
1523 __ lw(a1, MemOperand(fp, kFunctionOffset)); | |
1524 __ GetObjectType(a1, a2, a2); | |
1525 __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE)); | |
1526 | |
1527 // Change context eagerly to get the right global object if necessary. | |
1528 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | |
1529 // Load the shared function info while the function is still in a1. | |
1530 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | |
1531 | |
1532 // Compute the receiver. | |
1533 // Do not transform the receiver for strict mode functions. | |
1534 Label call_to_object, use_global_proxy; | |
1535 __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset)); | |
1536 __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + | |
1537 kSmiTagSize))); | |
1538 __ Branch(&push_receiver, ne, t3, Operand(zero_reg)); | |
1539 | |
1540 // Do not transform the receiver for native (Compilerhints already in a2). | |
1541 __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); | |
1542 __ Branch(&push_receiver, ne, t3, Operand(zero_reg)); | |
1543 | |
1544 // Compute the receiver in sloppy mode. | |
1545 __ JumpIfSmi(a0, &call_to_object); | |
1546 __ LoadRoot(a1, Heap::kNullValueRootIndex); | |
1547 __ Branch(&use_global_proxy, eq, a0, Operand(a1)); | |
1548 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); | |
1549 __ Branch(&use_global_proxy, eq, a0, Operand(a2)); | |
1550 | |
1551 // Check if the receiver is already a JavaScript object. | |
1552 // a0: receiver | |
1553 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | |
1554 __ GetObjectType(a0, a1, a1); | |
1555 __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); | |
1556 | |
1557 // Convert the receiver to a regular object. | |
1558 // a0: receiver | |
1559 __ bind(&call_to_object); | |
1560 ToObjectStub stub(masm->isolate()); | |
1561 __ CallStub(&stub); | |
1562 __ mov(a0, v0); // Put object in a0 to match other paths to push_receiver. | |
1563 __ Branch(&push_receiver); | |
1564 | |
1565 __ bind(&use_global_proxy); | |
1566 __ lw(a0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | |
1567 __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalProxyOffset)); | |
1568 | |
1569 // Push the receiver. | |
1570 // a0: receiver | |
1571 __ bind(&push_receiver); | |
1572 __ push(a0); | |
1573 | 1381 |
1574 // Copy all arguments from the array to the stack. | 1382 // Copy all arguments from the array to the stack. |
1575 Generate_PushAppliedArguments( | 1383 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset, |
1576 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); | 1384 kLimitOffset); |
1577 | 1385 |
1578 // Call the function. | 1386 // Call the callable. |
1579 Label call_proxy; | 1387 // TODO(bmeurer): This should be a tail call according to ES6. |
1580 ParameterCount actual(a0); | |
1581 __ lw(a1, MemOperand(fp, kFunctionOffset)); | 1388 __ lw(a1, MemOperand(fp, kFunctionOffset)); |
1582 __ GetObjectType(a1, a2, a2); | 1389 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1583 __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE)); | |
1584 | 1390 |
1585 __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper()); | |
1586 | |
1587 frame_scope.GenerateLeaveFrame(); | |
1588 __ Ret(USE_DELAY_SLOT); | |
1589 __ Addu(sp, sp, Operand(kStackSize * kPointerSize)); // In delay slot. | |
1590 | |
1591 // Call the function proxy. | |
1592 __ bind(&call_proxy); | |
1593 __ push(a1); // Add function proxy as last argument. | |
1594 __ Addu(a0, a0, Operand(1)); | |
1595 __ li(a2, Operand(0, RelocInfo::NONE32)); | |
1596 __ GetBuiltinFunction(a1, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX); | |
1597 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
1598 RelocInfo::CODE_TARGET); | |
1599 // Tear down the internal frame and remove function, receiver and args. | 1391 // Tear down the internal frame and remove function, receiver and args. |
1600 } | 1392 } |
1601 | 1393 |
1602 __ Ret(USE_DELAY_SLOT); | 1394 __ Ret(USE_DELAY_SLOT); |
1603 __ Addu(sp, sp, Operand(kStackSize * kPointerSize)); // In delay slot. | 1395 __ Addu(sp, sp, Operand(kStackSize * kPointerSize)); // In delay slot. |
1604 } | 1396 } |
1605 | 1397 |
1606 | 1398 |
1607 static void Generate_ConstructHelper(MacroAssembler* masm) { | 1399 static void Generate_ConstructHelper(MacroAssembler* masm) { |
1608 const int kFormalParameters = 3; | 1400 const int kFormalParameters = 3; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1724 kPointerSize))); | 1516 kPointerSize))); |
1725 __ mov(sp, fp); | 1517 __ mov(sp, fp); |
1726 __ MultiPop(fp.bit() | ra.bit()); | 1518 __ MultiPop(fp.bit() | ra.bit()); |
1727 __ sll(t0, a1, kPointerSizeLog2 - kSmiTagSize); | 1519 __ sll(t0, a1, kPointerSizeLog2 - kSmiTagSize); |
1728 __ Addu(sp, sp, t0); | 1520 __ Addu(sp, sp, t0); |
1729 // Adjust for the receiver. | 1521 // Adjust for the receiver. |
1730 __ Addu(sp, sp, Operand(kPointerSize)); | 1522 __ Addu(sp, sp, Operand(kPointerSize)); |
1731 } | 1523 } |
1732 | 1524 |
1733 | 1525 |
| 1526 // static |
| 1527 void Builtins::Generate_CallFunction(MacroAssembler* masm) { |
| 1528 // ----------- S t a t e ------------- |
| 1529 // -- a0 : the number of arguments (not including the receiver) |
| 1530 // -- a1 : the function to call (checked to be a JSFunction) |
| 1531 // ----------------------------------- |
| 1532 |
| 1533 Label convert, convert_global_proxy, convert_to_object, done_convert; |
| 1534 __ AssertFunction(a1); |
| 1535 // TODO(bmeurer): Throw a TypeError if function's [[FunctionKind]] internal |
| 1536 // slot is "classConstructor". |
| 1537 // Enter the context of the function; ToObject has to run in the function |
| 1538 // context, and we also need to take the global proxy from the function |
| 1539 // context in case of conversion. |
| 1540 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
| 1541 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == |
| 1542 SharedFunctionInfo::kStrictModeByteOffset); |
| 1543 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 1544 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1545 // We need to convert the receiver for non-native sloppy mode functions. |
| 1546 __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kNativeByteOffset)); |
| 1547 __ And(at, a3, Operand((1 << SharedFunctionInfo::kNativeBitWithinByte) | |
| 1548 (1 << SharedFunctionInfo::kStrictModeBitWithinByte))); |
| 1549 __ Branch(&done_convert, ne, at, Operand(zero_reg)); |
| 1550 { |
| 1551 __ sll(at, a0, kPointerSizeLog2); |
| 1552 __ addu(at, sp, at); |
| 1553 __ lw(a3, MemOperand(at)); |
| 1554 |
| 1555 // ----------- S t a t e ------------- |
| 1556 // -- a0 : the number of arguments (not including the receiver) |
| 1557 // -- a1 : the function to call (checked to be a JSFunction) |
| 1558 // -- a2 : the shared function info. |
| 1559 // -- a3 : the receiver |
| 1560 // -- cp : the function context. |
| 1561 // ----------------------------------- |
| 1562 |
| 1563 Label convert_receiver; |
| 1564 __ JumpIfSmi(a3, &convert_to_object); |
| 1565 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 1566 __ GetObjectType(a3, t0, t0); |
| 1567 __ Branch(&done_convert, hs, t0, Operand(FIRST_JS_RECEIVER_TYPE)); |
| 1568 __ JumpIfRoot(a3, Heap::kUndefinedValueRootIndex, &convert_global_proxy); |
| 1569 __ JumpIfNotRoot(a3, Heap::kNullValueRootIndex, &convert_to_object); |
| 1570 __ bind(&convert_global_proxy); |
| 1571 { |
| 1572 // Patch receiver to global proxy. |
| 1573 __ LoadGlobalProxy(a3); |
| 1574 } |
| 1575 __ Branch(&convert_receiver); |
| 1576 __ bind(&convert_to_object); |
| 1577 { |
| 1578 // Convert receiver using ToObject. |
| 1579 // TODO(bmeurer): Inline the allocation here to avoid building the frame |
| 1580 // in the fast case? (fall back to AllocateInNewSpace?) |
| 1581 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1582 __ sll(a0, a0, kSmiTagSize); // Smi tagged. |
| 1583 __ Push(a0, a1); |
| 1584 __ mov(a0, a3); |
| 1585 ToObjectStub stub(masm->isolate()); |
| 1586 __ CallStub(&stub); |
| 1587 __ mov(a3, v0); |
| 1588 __ Pop(a0, a1); |
| 1589 __ sra(a0, a0, kSmiTagSize); // Un-tag. |
| 1590 } |
| 1591 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1592 __ bind(&convert_receiver); |
| 1593 __ sll(at, a0, kPointerSizeLog2); |
| 1594 __ addu(at, sp, at); |
| 1595 __ sw(a3, MemOperand(at)); |
| 1596 } |
| 1597 __ bind(&done_convert); |
| 1598 |
| 1599 // ----------- S t a t e ------------- |
| 1600 // -- a0 : the number of arguments (not including the receiver) |
| 1601 // -- a1 : the function to call (checked to be a JSFunction) |
| 1602 // -- a2 : the shared function info. |
| 1603 // -- cp : the function context. |
| 1604 // ----------------------------------- |
| 1605 |
| 1606 __ lw(a2, |
| 1607 FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 1608 __ sra(a2, a2, kSmiTagSize); // Un-tag. |
| 1609 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 1610 ParameterCount actual(a0); |
| 1611 ParameterCount expected(a2); |
| 1612 __ InvokeCode(a3, expected, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 1613 } |
| 1614 |
| 1615 |
| 1616 // static |
| 1617 void Builtins::Generate_Call(MacroAssembler* masm) { |
| 1618 // ----------- S t a t e ------------- |
| 1619 // -- a0 : the number of arguments (not including the receiver) |
| 1620 // -- a1 : the target to call (can be any Object). |
| 1621 // ----------------------------------- |
| 1622 |
| 1623 Label non_smi, non_function; |
| 1624 __ JumpIfSmi(a1, &non_function); |
| 1625 __ bind(&non_smi); |
| 1626 __ GetObjectType(a1, a2, a2); |
| 1627 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET, |
| 1628 eq, a2, Operand(JS_FUNCTION_TYPE)); |
| 1629 __ Branch(&non_function, ne, a2, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 1630 |
| 1631 |
| 1632 // 1. Call to function proxy. |
| 1633 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. |
| 1634 __ lw(a1, FieldMemOperand(a1, JSFunctionProxy::kCallTrapOffset)); |
| 1635 __ AssertNotSmi(a1); |
| 1636 __ Branch(&non_smi); |
| 1637 |
| 1638 // 2. Call to something else, which might have a [[Call]] internal method (if |
| 1639 // not we raise an exception). |
| 1640 __ bind(&non_function); |
| 1641 // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could |
| 1642 // be awesome instead; i.e. a trivial improvement would be to call into the |
| 1643 // runtime and just deal with the API function there instead of returning a |
| 1644 // delegate from a runtime call that just jumps back to the runtime once |
| 1645 // called. Or, bonus points, call directly into the C API function here, as |
| 1646 // we do in some Crankshaft fast cases. |
| 1647 // Overwrite the original receiver with the (original) target. |
| 1648 __ sll(at, a0, kPointerSizeLog2); |
| 1649 __ addu(at, sp, at); |
| 1650 __ sw(a1, MemOperand(at)); |
| 1651 { |
| 1652 // Determine the delegate for the target (if any). |
| 1653 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1654 __ sll(a0, a0, kSmiTagSize); // Smi tagged. |
| 1655 __ Push(a0, a1); |
| 1656 __ CallRuntime(Runtime::kGetFunctionDelegate, 1); |
| 1657 __ mov(a1, v0); |
| 1658 __ Pop(a0); |
| 1659 __ sra(a0, a0, kSmiTagSize); // Un-tag. |
| 1660 } |
| 1661 // The delegate is always a regular function. |
| 1662 __ AssertFunction(a1); |
| 1663 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); |
| 1664 } |
| 1665 |
| 1666 |
1734 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { | 1667 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { |
1735 // State setup as expected by MacroAssembler::InvokePrologue. | 1668 // State setup as expected by MacroAssembler::InvokePrologue. |
1736 // ----------- S t a t e ------------- | 1669 // ----------- S t a t e ------------- |
1737 // -- a0: actual arguments count | 1670 // -- a0: actual arguments count |
1738 // -- a1: function (passed through to callee) | 1671 // -- a1: function (passed through to callee) |
1739 // -- a2: expected arguments count | 1672 // -- a2: expected arguments count |
1740 // ----------------------------------- | 1673 // ----------------------------------- |
1741 | 1674 |
1742 Label stack_overflow; | 1675 Label stack_overflow; |
1743 ArgumentAdaptorStackCheck(masm, &stack_overflow); | 1676 ArgumentAdaptorStackCheck(masm, &stack_overflow); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1883 } | 1816 } |
1884 } | 1817 } |
1885 | 1818 |
1886 | 1819 |
1887 #undef __ | 1820 #undef __ |
1888 | 1821 |
1889 } // namespace internal | 1822 } // namespace internal |
1890 } // namespace v8 | 1823 } // namespace v8 |
1891 | 1824 |
1892 #endif // V8_TARGET_ARCH_MIPS | 1825 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |