| 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_MIPS64 | 5 #if V8_TARGET_ARCH_MIPS64 |
| 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 1311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1322 // (which is a copy of the last argument). | 1322 // (which is a copy of the last argument). |
| 1323 __ Dsubu(a0, a0, Operand(1)); | 1323 __ Dsubu(a0, a0, Operand(1)); |
| 1324 __ Pop(); | 1324 __ Pop(); |
| 1325 } | 1325 } |
| 1326 | 1326 |
| 1327 // 4. Call the callable. | 1327 // 4. Call the callable. |
| 1328 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1328 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1329 } | 1329 } |
| 1330 | 1330 |
| 1331 | 1331 |
| 1332 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
| 1333 const int vectorOffset, |
| 1334 const int argumentsOffset, |
| 1335 const int indexOffset, |
| 1336 const int limitOffset) { |
| 1337 Label entry, loop; |
| 1338 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 1339 Register key = LoadDescriptor::NameRegister(); |
| 1340 Register slot = LoadDescriptor::SlotRegister(); |
| 1341 Register vector = LoadWithVectorDescriptor::VectorRegister(); |
| 1342 |
| 1343 __ ld(key, MemOperand(fp, indexOffset)); |
| 1344 __ Branch(&entry); |
| 1345 |
| 1346 // Load the current argument from the arguments array. |
| 1347 __ bind(&loop); |
| 1348 __ ld(receiver, MemOperand(fp, argumentsOffset)); |
| 1349 |
| 1350 // Use inline caching to speed up access to arguments. |
| 1351 int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex(); |
| 1352 __ li(slot, Operand(Smi::FromInt(slot_index))); |
| 1353 __ ld(vector, MemOperand(fp, vectorOffset)); |
| 1354 Handle<Code> ic = |
| 1355 KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); |
| 1356 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1357 |
| 1358 __ push(v0); |
| 1359 |
| 1360 // Use inline caching to access the arguments. |
| 1361 __ ld(key, MemOperand(fp, indexOffset)); |
| 1362 __ Daddu(key, key, Operand(Smi::FromInt(1))); |
| 1363 __ sd(key, MemOperand(fp, indexOffset)); |
| 1364 |
| 1365 // Test if the copy loop has finished copying all the elements from the |
| 1366 // arguments object. |
| 1367 __ bind(&entry); |
| 1368 __ ld(a1, MemOperand(fp, limitOffset)); |
| 1369 __ Branch(&loop, ne, key, Operand(a1)); |
| 1370 |
| 1371 // On exit, the pushed arguments count is in a0, untagged |
| 1372 __ mov(a0, key); |
| 1373 __ SmiUntag(a0); |
| 1374 } |
| 1375 |
| 1376 |
| 1377 // Used by FunctionApply and ReflectApply |
| 1378 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { |
| 1379 const int kFormalParameters = targetIsArgument ? 3 : 2; |
| 1380 const int kStackSize = kFormalParameters + 1; |
| 1381 |
| 1382 { |
| 1383 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
| 1384 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; |
| 1385 const int kReceiverOffset = kArgumentsOffset + kPointerSize; |
| 1386 const int kFunctionOffset = kReceiverOffset + kPointerSize; |
| 1387 const int kVectorOffset = |
| 1388 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; |
| 1389 |
| 1390 // Push the vector. |
| 1391 __ ld(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1392 __ ld(a1, FieldMemOperand(a1, SharedFunctionInfo::kFeedbackVectorOffset)); |
| 1393 __ Push(a1); |
| 1394 |
| 1395 __ ld(a0, MemOperand(fp, kFunctionOffset)); // Get the function. |
| 1396 __ ld(a1, MemOperand(fp, kArgumentsOffset)); // Get the args array. |
| 1397 __ Push(a0, a1); |
| 1398 |
| 1399 // Returns (in v0) number of arguments to copy to stack as Smi. |
| 1400 if (targetIsArgument) { |
| 1401 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, |
| 1402 CALL_FUNCTION); |
| 1403 } else { |
| 1404 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); |
| 1405 } |
| 1406 |
| 1407 // Returns the result in v0. |
| 1408 Generate_CheckStackOverflow(masm, v0, kArgcIsSmiTagged); |
| 1409 |
| 1410 // Push current limit and index. |
| 1411 const int kIndexOffset = kVectorOffset - (2 * kPointerSize); |
| 1412 const int kLimitOffset = kVectorOffset - (1 * kPointerSize); |
| 1413 __ mov(a1, zero_reg); |
| 1414 __ ld(a2, MemOperand(fp, kReceiverOffset)); |
| 1415 __ Push(v0, a1, a2); // limit, initial index and receiver. |
| 1416 |
| 1417 // Copy all arguments from the array to the stack. |
| 1418 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, |
| 1419 kIndexOffset, kLimitOffset); |
| 1420 |
| 1421 // Call the callable. |
| 1422 // TODO(bmeurer): This should be a tail call according to ES6. |
| 1423 __ ld(a1, MemOperand(fp, kFunctionOffset)); |
| 1424 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1425 |
| 1426 // Tear down the internal frame and remove function, receiver and args. |
| 1427 } |
| 1428 |
| 1429 __ Ret(USE_DELAY_SLOT); |
| 1430 __ Daddu(sp, sp, Operand(kStackSize * kPointerSize)); // In delay slot. |
| 1431 } |
| 1432 |
| 1433 |
| 1434 static void Generate_ConstructHelper(MacroAssembler* masm) { |
| 1435 const int kFormalParameters = 3; |
| 1436 const int kStackSize = kFormalParameters + 1; |
| 1437 |
| 1438 { |
| 1439 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
| 1440 const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; |
| 1441 const int kArgumentsOffset = kNewTargetOffset + kPointerSize; |
| 1442 const int kFunctionOffset = kArgumentsOffset + kPointerSize; |
| 1443 const int kVectorOffset = |
| 1444 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; |
| 1445 |
| 1446 // Push the vector. |
| 1447 __ ld(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1448 __ ld(a1, FieldMemOperand(a1, SharedFunctionInfo::kFeedbackVectorOffset)); |
| 1449 __ Push(a1); |
| 1450 |
| 1451 // If newTarget is not supplied, set it to constructor |
| 1452 Label validate_arguments; |
| 1453 __ ld(a0, MemOperand(fp, kNewTargetOffset)); |
| 1454 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 1455 __ Branch(&validate_arguments, ne, a0, Operand(at)); |
| 1456 __ ld(a0, MemOperand(fp, kFunctionOffset)); |
| 1457 __ sd(a0, MemOperand(fp, kNewTargetOffset)); |
| 1458 |
| 1459 // Validate arguments |
| 1460 __ bind(&validate_arguments); |
| 1461 __ ld(a0, MemOperand(fp, kFunctionOffset)); // get the function |
| 1462 __ push(a0); |
| 1463 __ ld(a0, MemOperand(fp, kArgumentsOffset)); // get the args array |
| 1464 __ push(a0); |
| 1465 __ ld(a0, MemOperand(fp, kNewTargetOffset)); // get the new.target |
| 1466 __ push(a0); |
| 1467 // Returns argument count in v0. |
| 1468 __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, |
| 1469 CALL_FUNCTION); |
| 1470 |
| 1471 // Returns result in v0. |
| 1472 Generate_CheckStackOverflow(masm, v0, kArgcIsSmiTagged); |
| 1473 |
| 1474 // Push current limit and index. |
| 1475 const int kIndexOffset = kVectorOffset - (2 * kPointerSize); |
| 1476 const int kLimitOffset = kVectorOffset - (1 * kPointerSize); |
| 1477 __ push(v0); // limit |
| 1478 __ mov(a1, zero_reg); // initial index |
| 1479 __ push(a1); |
| 1480 // Push the constructor function as callee. |
| 1481 __ ld(a0, MemOperand(fp, kFunctionOffset)); |
| 1482 __ push(a0); |
| 1483 |
| 1484 // Copy all arguments from the array to the stack. |
| 1485 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, |
| 1486 kIndexOffset, kLimitOffset); |
| 1487 |
| 1488 // Use undefined feedback vector |
| 1489 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); |
| 1490 __ ld(a1, MemOperand(fp, kFunctionOffset)); |
| 1491 __ ld(a3, MemOperand(fp, kNewTargetOffset)); |
| 1492 |
| 1493 // Call the function. |
| 1494 __ Call(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 1495 |
| 1496 // Leave internal frame. |
| 1497 } |
| 1498 __ jr(ra); |
| 1499 __ Daddu(sp, sp, Operand(kStackSize * kPointerSize)); // In delay slot. |
| 1500 } |
| 1501 |
| 1502 |
| 1332 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1503 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| 1333 // ----------- S t a t e ------------- | 1504 Generate_ApplyHelper(masm, false); |
| 1334 // -- a0 : argc | |
| 1335 // -- sp[0] : argArray | |
| 1336 // -- sp[4] : thisArg | |
| 1337 // -- sp[8] : receiver | |
| 1338 // ----------------------------------- | |
| 1339 | |
| 1340 // 1. Load receiver into a1, argArray into a0 (if present), remove all | |
| 1341 // arguments from the stack (including the receiver), and push thisArg (if | |
| 1342 // present) instead. | |
| 1343 { | |
| 1344 Label no_arg; | |
| 1345 Register scratch = a4; | |
| 1346 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); | |
| 1347 __ mov(a3, a2); | |
| 1348 __ dsll(scratch, a0, kPointerSizeLog2); | |
| 1349 __ Daddu(a0, sp, Operand(scratch)); | |
| 1350 __ ld(a1, MemOperand(a0)); // receiver | |
| 1351 __ Dsubu(a0, a0, Operand(kPointerSize)); | |
| 1352 __ Branch(&no_arg, lt, a0, Operand(sp)); | |
| 1353 __ ld(a2, MemOperand(a0)); // thisArg | |
| 1354 __ Dsubu(a0, a0, Operand(kPointerSize)); | |
| 1355 __ Branch(&no_arg, lt, a0, Operand(sp)); | |
| 1356 __ ld(a3, MemOperand(a0)); // argArray | |
| 1357 __ bind(&no_arg); | |
| 1358 __ Daddu(sp, sp, Operand(scratch)); | |
| 1359 __ sd(a2, MemOperand(sp)); | |
| 1360 __ mov(a0, a3); | |
| 1361 } | |
| 1362 | |
| 1363 // ----------- S t a t e ------------- | |
| 1364 // -- a0 : argArray | |
| 1365 // -- a1 : receiver | |
| 1366 // -- sp[0] : thisArg | |
| 1367 // ----------------------------------- | |
| 1368 | |
| 1369 // 2. Make sure the receiver is actually callable. | |
| 1370 Label receiver_not_callable; | |
| 1371 __ JumpIfSmi(a1, &receiver_not_callable); | |
| 1372 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset)); | |
| 1373 __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); | |
| 1374 __ And(a4, a4, Operand(1 << Map::kIsCallable)); | |
| 1375 __ Branch(&receiver_not_callable, eq, a4, Operand(zero_reg)); | |
| 1376 | |
| 1377 // 3. Tail call with no arguments if argArray is null or undefined. | |
| 1378 Label no_arguments; | |
| 1379 __ JumpIfRoot(a0, Heap::kNullValueRootIndex, &no_arguments); | |
| 1380 __ JumpIfRoot(a0, Heap::kUndefinedValueRootIndex, &no_arguments); | |
| 1381 | |
| 1382 // 4a. Apply the receiver to the given argArray (passing undefined for | |
| 1383 // new.target). | |
| 1384 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex); | |
| 1385 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
| 1386 | |
| 1387 // 4b. The argArray is either null or undefined, so we tail call without any | |
| 1388 // arguments to the receiver. | |
| 1389 __ bind(&no_arguments); | |
| 1390 { | |
| 1391 __ mov(a0, zero_reg); | |
| 1392 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
| 1393 } | |
| 1394 | |
| 1395 // 4c. The receiver is not callable, throw an appropriate TypeError. | |
| 1396 __ bind(&receiver_not_callable); | |
| 1397 { | |
| 1398 __ sd(a1, MemOperand(sp)); | |
| 1399 __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1); | |
| 1400 } | |
| 1401 } | 1505 } |
| 1402 | 1506 |
| 1403 | 1507 |
| 1404 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | 1508 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { |
| 1405 // ----------- S t a t e ------------- | 1509 Generate_ApplyHelper(masm, true); |
| 1406 // -- a0 : argc | |
| 1407 // -- sp[0] : argumentsList | |
| 1408 // -- sp[4] : thisArgument | |
| 1409 // -- sp[8] : target | |
| 1410 // -- sp[12] : receiver | |
| 1411 // ----------------------------------- | |
| 1412 | |
| 1413 // 1. Load target into a1 (if present), argumentsList into a0 (if present), | |
| 1414 // remove all arguments from the stack (including the receiver), and push | |
| 1415 // thisArgument (if present) instead. | |
| 1416 { | |
| 1417 Label no_arg; | |
| 1418 Register scratch = a4; | |
| 1419 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); | |
| 1420 __ mov(a2, a1); | |
| 1421 __ mov(a3, a1); | |
| 1422 __ dsll(scratch, a0, kPointerSizeLog2); | |
| 1423 __ mov(a0, scratch); | |
| 1424 __ Dsubu(a0, a0, Operand(kPointerSize)); | |
| 1425 __ Branch(&no_arg, lt, a0, Operand(zero_reg)); | |
| 1426 __ Daddu(a0, sp, Operand(a0)); | |
| 1427 __ ld(a1, MemOperand(a0)); // target | |
| 1428 __ Dsubu(a0, a0, Operand(kPointerSize)); | |
| 1429 __ Branch(&no_arg, lt, a0, Operand(sp)); | |
| 1430 __ ld(a2, MemOperand(a0)); // thisArgument | |
| 1431 __ Dsubu(a0, a0, Operand(kPointerSize)); | |
| 1432 __ Branch(&no_arg, lt, a0, Operand(sp)); | |
| 1433 __ ld(a3, MemOperand(a0)); // argumentsList | |
| 1434 __ bind(&no_arg); | |
| 1435 __ Daddu(sp, sp, Operand(scratch)); | |
| 1436 __ sd(a2, MemOperand(sp)); | |
| 1437 __ mov(a0, a3); | |
| 1438 } | |
| 1439 | |
| 1440 // ----------- S t a t e ------------- | |
| 1441 // -- a0 : argumentsList | |
| 1442 // -- a1 : target | |
| 1443 // -- sp[0] : thisArgument | |
| 1444 // ----------------------------------- | |
| 1445 | |
| 1446 // 2. Make sure the target is actually callable. | |
| 1447 Label target_not_callable; | |
| 1448 __ JumpIfSmi(a1, &target_not_callable); | |
| 1449 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset)); | |
| 1450 __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); | |
| 1451 __ And(a4, a4, Operand(1 << Map::kIsCallable)); | |
| 1452 __ Branch(&target_not_callable, eq, a4, Operand(zero_reg)); | |
| 1453 | |
| 1454 // 3a. Apply the target to the given argumentsList (passing undefined for | |
| 1455 // new.target). | |
| 1456 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex); | |
| 1457 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
| 1458 | |
| 1459 // 3b. The target is not callable, throw an appropriate TypeError. | |
| 1460 __ bind(&target_not_callable); | |
| 1461 { | |
| 1462 __ sd(a1, MemOperand(sp)); | |
| 1463 __ TailCallRuntime(Runtime::kThrowApplyNonFunction, 1, 1); | |
| 1464 } | |
| 1465 } | 1510 } |
| 1466 | 1511 |
| 1467 | 1512 |
| 1468 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | 1513 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { |
| 1469 // ----------- S t a t e ------------- | 1514 Generate_ConstructHelper(masm); |
| 1470 // -- a0 : argc | |
| 1471 // -- sp[0] : new.target (optional) | |
| 1472 // -- sp[4] : argumentsList | |
| 1473 // -- sp[8] : target | |
| 1474 // -- sp[12] : receiver | |
| 1475 // ----------------------------------- | |
| 1476 | |
| 1477 // 1. Load target into a1 (if present), argumentsList into a0 (if present), | |
| 1478 // new.target into a3 (if present, otherwise use target), remove all | |
| 1479 // arguments from the stack (including the receiver), and push thisArgument | |
| 1480 // (if present) instead. | |
| 1481 { | |
| 1482 Label no_arg; | |
| 1483 Register scratch = a4; | |
| 1484 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); | |
| 1485 __ mov(a2, a1); | |
| 1486 __ dsll(scratch, a0, kPointerSizeLog2); | |
| 1487 __ Daddu(a0, sp, Operand(scratch)); | |
| 1488 __ sd(a2, MemOperand(a0)); // receiver | |
| 1489 __ Dsubu(a0, a0, Operand(kPointerSize)); | |
| 1490 __ Branch(&no_arg, lt, a0, Operand(sp)); | |
| 1491 __ ld(a1, MemOperand(a0)); // target | |
| 1492 __ mov(a3, a1); // new.target defaults to target | |
| 1493 __ Dsubu(a0, a0, Operand(kPointerSize)); | |
| 1494 __ Branch(&no_arg, lt, a0, Operand(sp)); | |
| 1495 __ ld(a2, MemOperand(a0)); // argumentsList | |
| 1496 __ Dsubu(a0, a0, Operand(kPointerSize)); | |
| 1497 __ Branch(&no_arg, lt, a0, Operand(sp)); | |
| 1498 __ ld(a3, MemOperand(a0)); // new.target | |
| 1499 __ bind(&no_arg); | |
| 1500 __ Daddu(sp, sp, Operand(scratch)); | |
| 1501 __ mov(a0, a2); | |
| 1502 } | |
| 1503 | |
| 1504 // ----------- S t a t e ------------- | |
| 1505 // -- a0 : argumentsList | |
| 1506 // -- a3 : new.target | |
| 1507 // -- a1 : target | |
| 1508 // -- sp[0] : receiver (undefined) | |
| 1509 // ----------------------------------- | |
| 1510 | |
| 1511 // 2. Make sure the target is actually a constructor. | |
| 1512 Label target_not_constructor; | |
| 1513 __ JumpIfSmi(a1, &target_not_constructor); | |
| 1514 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset)); | |
| 1515 __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); | |
| 1516 __ And(a4, a4, Operand(1 << Map::kIsConstructor)); | |
| 1517 __ Branch(&target_not_constructor, eq, a4, Operand(zero_reg)); | |
| 1518 | |
| 1519 // 3. Make sure the target is actually a constructor. | |
| 1520 Label new_target_not_constructor; | |
| 1521 __ JumpIfSmi(a3, &new_target_not_constructor); | |
| 1522 __ ld(a4, FieldMemOperand(a3, HeapObject::kMapOffset)); | |
| 1523 __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); | |
| 1524 __ And(a4, a4, Operand(1 << Map::kIsConstructor)); | |
| 1525 __ Branch(&new_target_not_constructor, eq, a4, Operand(zero_reg)); | |
| 1526 | |
| 1527 // 4a. Construct the target with the given new.target and argumentsList. | |
| 1528 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
| 1529 | |
| 1530 // 4b. The target is not a constructor, throw an appropriate TypeError. | |
| 1531 __ bind(&target_not_constructor); | |
| 1532 { | |
| 1533 __ sd(a1, MemOperand(sp)); | |
| 1534 __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1); | |
| 1535 } | |
| 1536 | |
| 1537 // 4c. The new.target is not a constructor, throw an appropriate TypeError. | |
| 1538 __ bind(&new_target_not_constructor); | |
| 1539 { | |
| 1540 __ sd(a3, MemOperand(sp)); | |
| 1541 __ TailCallRuntime(Runtime::kThrowCalledNonCallable, 1, 1); | |
| 1542 } | |
| 1543 } | 1515 } |
| 1544 | 1516 |
| 1545 | 1517 |
| 1546 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, | 1518 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, |
| 1547 Label* stack_overflow) { | 1519 Label* stack_overflow) { |
| 1548 // ----------- S t a t e ------------- | 1520 // ----------- S t a t e ------------- |
| 1549 // -- a0 : actual number of arguments | 1521 // -- a0 : actual number of arguments |
| 1550 // -- a1 : function (passed through to callee) | 1522 // -- a1 : function (passed through to callee) |
| 1551 // -- a2 : expected number of arguments | 1523 // -- a2 : expected number of arguments |
| 1552 // -- a3 : new target (passed through to callee) | 1524 // -- a3 : new target (passed through to callee) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1585 kPointerSize))); | 1557 kPointerSize))); |
| 1586 __ mov(sp, fp); | 1558 __ mov(sp, fp); |
| 1587 __ MultiPop(fp.bit() | ra.bit()); | 1559 __ MultiPop(fp.bit() | ra.bit()); |
| 1588 __ SmiScale(a4, a1, kPointerSizeLog2); | 1560 __ SmiScale(a4, a1, kPointerSizeLog2); |
| 1589 __ Daddu(sp, sp, a4); | 1561 __ Daddu(sp, sp, a4); |
| 1590 // Adjust for the receiver. | 1562 // Adjust for the receiver. |
| 1591 __ Daddu(sp, sp, Operand(kPointerSize)); | 1563 __ Daddu(sp, sp, Operand(kPointerSize)); |
| 1592 } | 1564 } |
| 1593 | 1565 |
| 1594 | 1566 |
| 1595 // static | |
| 1596 void Builtins::Generate_Apply(MacroAssembler* masm) { | |
| 1597 // ----------- S t a t e ------------- | |
| 1598 // -- a0 : argumentsList | |
| 1599 // -- a1 : target | |
| 1600 // -- a3 : new.target (checked to be constructor or undefined) | |
| 1601 // -- sp[0] : thisArgument | |
| 1602 // ----------------------------------- | |
| 1603 | |
| 1604 // Create the list of arguments from the array-like argumentsList. | |
| 1605 { | |
| 1606 Label create_arguments, create_array, create_runtime, done_create; | |
| 1607 __ JumpIfSmi(a0, &create_runtime); | |
| 1608 | |
| 1609 // Load the map of argumentsList into a2. | |
| 1610 __ ld(a2, FieldMemOperand(a0, HeapObject::kMapOffset)); | |
| 1611 | |
| 1612 // Load native context into a4. | |
| 1613 __ ld(a4, NativeContextMemOperand()); | |
| 1614 | |
| 1615 // Check if argumentsList is an (unmodified) arguments object. | |
| 1616 __ ld(at, ContextMemOperand(a4, Context::SLOPPY_ARGUMENTS_MAP_INDEX)); | |
| 1617 __ Branch(&create_arguments, eq, a2, Operand(at)); | |
| 1618 __ ld(at, ContextMemOperand(a4, Context::STRICT_ARGUMENTS_MAP_INDEX)); | |
| 1619 __ Branch(&create_arguments, eq, a2, Operand(at)); | |
| 1620 | |
| 1621 // Check if argumentsList is a fast JSArray. | |
| 1622 __ ld(v0, FieldMemOperand(a2, HeapObject::kMapOffset)); | |
| 1623 __ lbu(v0, FieldMemOperand(v0, Map::kInstanceTypeOffset)); | |
| 1624 __ Branch(&create_array, eq, v0, Operand(JS_ARRAY_TYPE)); | |
| 1625 | |
| 1626 // Ask the runtime to create the list (actually a FixedArray). | |
| 1627 __ bind(&create_runtime); | |
| 1628 { | |
| 1629 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 1630 __ Push(a1, a3, a0); | |
| 1631 __ CallRuntime(Runtime::kCreateListFromArrayLike, 1); | |
| 1632 __ mov(a0, v0); | |
| 1633 __ Pop(a1, a3); | |
| 1634 __ ld(a2, FieldMemOperand(v0, FixedArray::kLengthOffset)); | |
| 1635 __ SmiUntag(a2); | |
| 1636 } | |
| 1637 __ Branch(&done_create); | |
| 1638 | |
| 1639 // Try to create the list from an arguments object. | |
| 1640 __ bind(&create_arguments); | |
| 1641 __ ld(a2, | |
| 1642 FieldMemOperand(a0, JSObject::kHeaderSize + | |
| 1643 Heap::kArgumentsLengthIndex * kPointerSize)); | |
| 1644 __ ld(a4, FieldMemOperand(a0, JSObject::kElementsOffset)); | |
| 1645 __ ld(at, FieldMemOperand(a4, FixedArray::kLengthOffset)); | |
| 1646 __ Branch(&create_runtime, ne, a2, Operand(at)); | |
| 1647 __ SmiUntag(a2); | |
| 1648 __ mov(a0, a4); | |
| 1649 __ Branch(&done_create); | |
| 1650 | |
| 1651 // Try to create the list from a JSArray object. | |
| 1652 __ bind(&create_array); | |
| 1653 __ ld(a2, FieldMemOperand(a2, Map::kBitField2Offset)); | |
| 1654 __ DecodeField<Map::ElementsKindBits>(a2); | |
| 1655 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
| 1656 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
| 1657 STATIC_ASSERT(FAST_ELEMENTS == 2); | |
| 1658 __ Branch(&create_runtime, hi, a2, Operand(FAST_ELEMENTS)); | |
| 1659 __ Branch(&create_runtime, eq, a2, Operand(FAST_HOLEY_SMI_ELEMENTS)); | |
| 1660 __ ld(a2, FieldMemOperand(a0, JSArray::kLengthOffset)); | |
| 1661 __ ld(a0, FieldMemOperand(a0, JSArray::kElementsOffset)); | |
| 1662 __ SmiUntag(a2); | |
| 1663 | |
| 1664 __ bind(&done_create); | |
| 1665 } | |
| 1666 | |
| 1667 // Check for stack overflow. | |
| 1668 { | |
| 1669 // Check the stack for overflow. We are not trying to catch interruptions | |
| 1670 // (i.e. debug break and preemption) here, so check the "real stack limit". | |
| 1671 Label done; | |
| 1672 __ LoadRoot(a4, Heap::kRealStackLimitRootIndex); | |
| 1673 // Make ip the space we have left. The stack might already be overflowed | |
| 1674 // here which will cause ip to become negative. | |
| 1675 __ Dsubu(a4, sp, a4); | |
| 1676 // Check if the arguments will overflow the stack. | |
| 1677 __ dsll(at, a2, kPointerSizeLog2); | |
| 1678 __ Branch(&done, gt, a4, Operand(at)); // Signed comparison. | |
| 1679 __ TailCallRuntime(Runtime::kThrowStackOverflow, 1, 1); | |
| 1680 __ bind(&done); | |
| 1681 } | |
| 1682 | |
| 1683 // ----------- S t a t e ------------- | |
| 1684 // -- a1 : target | |
| 1685 // -- a0 : args (a FixedArray built from argumentsList) | |
| 1686 // -- a2 : len (number of elements to push from args) | |
| 1687 // -- a3 : new.target (checked to be constructor or undefined) | |
| 1688 // -- sp[0] : thisArgument | |
| 1689 // ----------------------------------- | |
| 1690 | |
| 1691 // Push arguments onto the stack (thisArgument is already on the stack). | |
| 1692 { | |
| 1693 __ mov(a4, zero_reg); | |
| 1694 Label done, loop; | |
| 1695 __ bind(&loop); | |
| 1696 __ Branch(&done, eq, a4, Operand(a2)); | |
| 1697 __ dsll(at, a4, kPointerSizeLog2); | |
| 1698 __ Daddu(at, a0, at); | |
| 1699 __ ld(at, FieldMemOperand(at, FixedArray::kHeaderSize)); | |
| 1700 __ Push(at); | |
| 1701 __ Daddu(a4, a4, Operand(1)); | |
| 1702 __ Branch(&loop); | |
| 1703 __ bind(&done); | |
| 1704 __ Move(a0, a4); | |
| 1705 } | |
| 1706 | |
| 1707 // Dispatch to Call or Construct depending on whether new.target is undefined. | |
| 1708 { | |
| 1709 Label construct; | |
| 1710 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | |
| 1711 __ Branch(&construct, ne, a3, Operand(at)); | |
| 1712 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
| 1713 __ bind(&construct); | |
| 1714 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | |
| 1715 } | |
| 1716 } | |
| 1717 | |
| 1718 | |
| 1719 // static | 1567 // static |
| 1720 void Builtins::Generate_CallFunction(MacroAssembler* masm, | 1568 void Builtins::Generate_CallFunction(MacroAssembler* masm, |
| 1721 ConvertReceiverMode mode) { | 1569 ConvertReceiverMode mode) { |
| 1722 // ----------- S t a t e ------------- | 1570 // ----------- S t a t e ------------- |
| 1723 // -- a0 : the number of arguments (not including the receiver) | 1571 // -- a0 : the number of arguments (not including the receiver) |
| 1724 // -- a1 : the function to call (checked to be a JSFunction) | 1572 // -- a1 : the function to call (checked to be a JSFunction) |
| 1725 // ----------------------------------- | 1573 // ----------------------------------- |
| 1726 __ AssertFunction(a1); | 1574 __ AssertFunction(a1); |
| 1727 | 1575 |
| 1728 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | 1576 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2118 } | 1966 } |
| 2119 } | 1967 } |
| 2120 | 1968 |
| 2121 | 1969 |
| 2122 #undef __ | 1970 #undef __ |
| 2123 | 1971 |
| 2124 } // namespace internal | 1972 } // namespace internal |
| 2125 } // namespace v8 | 1973 } // namespace v8 |
| 2126 | 1974 |
| 2127 #endif // V8_TARGET_ARCH_MIPS64 | 1975 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |