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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_MIPS | 7 #if V8_TARGET_ARCH_MIPS |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 | 1092 |
1093 | 1093 |
1094 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { | 1094 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { |
1095 CEntryStub stub(isolate, 1, kDontSaveFPRegs); | 1095 CEntryStub stub(isolate, 1, kDontSaveFPRegs); |
1096 stub.GetCode(); | 1096 stub.GetCode(); |
1097 } | 1097 } |
1098 | 1098 |
1099 | 1099 |
1100 void CEntryStub::Generate(MacroAssembler* masm) { | 1100 void CEntryStub::Generate(MacroAssembler* masm) { |
1101 // Called from JavaScript; parameters are on stack as if calling JS function | 1101 // Called from JavaScript; parameters are on stack as if calling JS function |
1102 // s0: number of arguments including receiver | 1102 // a0: number of arguments including receiver |
1103 // s1: size of arguments excluding receiver | 1103 // a1: pointer to builtin function |
1104 // s2: pointer to builtin function | |
1105 // fp: frame pointer (restored after C call) | 1104 // fp: frame pointer (restored after C call) |
1106 // sp: stack pointer (restored as callee's sp after C call) | 1105 // sp: stack pointer (restored as callee's sp after C call) |
1107 // cp: current context (C callee-saved) | 1106 // cp: current context (C callee-saved) |
1108 | 1107 |
1109 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 1108 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
1110 | 1109 |
1111 // NOTE: s0-s2 hold the arguments of this function instead of a0-a2. | |
1112 // The reason for this is that these arguments would need to be saved anyway | |
1113 // so it's faster to set them up directly. | |
1114 // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction. | |
1115 | |
1116 // Compute the argv pointer in a callee-saved register. | 1110 // Compute the argv pointer in a callee-saved register. |
| 1111 __ sll(s1, a0, kPointerSizeLog2); |
1117 __ Addu(s1, sp, s1); | 1112 __ Addu(s1, sp, s1); |
| 1113 __ Subu(s1, s1, kPointerSize); |
1118 | 1114 |
1119 // Enter the exit frame that transitions from JavaScript to C++. | 1115 // Enter the exit frame that transitions from JavaScript to C++. |
1120 FrameScope scope(masm, StackFrame::MANUAL); | 1116 FrameScope scope(masm, StackFrame::MANUAL); |
1121 __ EnterExitFrame(save_doubles()); | 1117 __ EnterExitFrame(save_doubles()); |
1122 | 1118 |
1123 // s0: number of arguments including receiver (C callee-saved) | 1119 // s0: number of arguments including receiver (C callee-saved) |
1124 // s1: pointer to first argument (C callee-saved) | 1120 // s1: pointer to first argument (C callee-saved) |
1125 // s2: pointer to builtin function (C callee-saved) | 1121 // s2: pointer to builtin function (C callee-saved) |
1126 | 1122 |
1127 // Prepare arguments for C routine. | 1123 // Prepare arguments for C routine. |
1128 // a0 = argc | 1124 // a0 = argc |
1129 __ mov(a0, s0); | 1125 __ mov(s0, a0); |
| 1126 __ mov(s2, a1); |
1130 // a1 = argv (set in the delay slot after find_ra below). | 1127 // a1 = argv (set in the delay slot after find_ra below). |
1131 | 1128 |
1132 // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We | 1129 // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We |
1133 // also need to reserve the 4 argument slots on the stack. | 1130 // also need to reserve the 4 argument slots on the stack. |
1134 | 1131 |
1135 __ AssertStackIsAligned(); | 1132 __ AssertStackIsAligned(); |
1136 | 1133 |
1137 __ li(a2, Operand(ExternalReference::isolate_address(isolate()))); | 1134 __ li(a2, Operand(ExternalReference::isolate_address(isolate()))); |
1138 | 1135 |
1139 // To let the GC traverse the return address of the exit frames, we need to | 1136 // To let the GC traverse the return address of the exit frames, we need to |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1410 // Expected input (depending on whether args are in registers or on the stack): | 1407 // Expected input (depending on whether args are in registers or on the stack): |
1411 // * object: a0 or at sp + 1 * kPointerSize. | 1408 // * object: a0 or at sp + 1 * kPointerSize. |
1412 // * function: a1 or at sp. | 1409 // * function: a1 or at sp. |
1413 // | 1410 // |
1414 // An inlined call site may have been generated before calling this stub. | 1411 // An inlined call site may have been generated before calling this stub. |
1415 // In this case the offset to the inline site to patch is passed on the stack, | 1412 // In this case the offset to the inline site to patch is passed on the stack, |
1416 // in the safepoint slot for register t0. | 1413 // in the safepoint slot for register t0. |
1417 void InstanceofStub::Generate(MacroAssembler* masm) { | 1414 void InstanceofStub::Generate(MacroAssembler* masm) { |
1418 // Call site inlining and patching implies arguments in registers. | 1415 // Call site inlining and patching implies arguments in registers. |
1419 DCHECK(HasArgsInRegisters() || !HasCallSiteInlineCheck()); | 1416 DCHECK(HasArgsInRegisters() || !HasCallSiteInlineCheck()); |
1420 // ReturnTrueFalse is only implemented for inlined call sites. | |
1421 DCHECK(!ReturnTrueFalseObject() || HasCallSiteInlineCheck()); | |
1422 | 1417 |
1423 // Fixed register usage throughout the stub: | 1418 // Fixed register usage throughout the stub: |
1424 const Register object = a0; // Object (lhs). | 1419 const Register object = a0; // Object (lhs). |
1425 Register map = a3; // Map of the object. | 1420 Register map = a3; // Map of the object. |
1426 const Register function = a1; // Function (rhs). | 1421 const Register function = a1; // Function (rhs). |
1427 const Register prototype = t0; // Prototype of the function. | 1422 const Register prototype = t0; // Prototype of the function. |
1428 const Register inline_site = t5; | 1423 const Register inline_site = t5; |
1429 const Register scratch = a2; | 1424 const Register scratch = a2; |
1430 | 1425 |
1431 const int32_t kDeltaToLoadBoolResult = 5 * kPointerSize; | 1426 const int32_t kDeltaToLoadBoolResult = 5 * kPointerSize; |
1432 | 1427 |
1433 Label slow, loop, is_instance, is_not_instance, not_js_object; | 1428 Label slow, loop, is_instance, is_not_instance, not_js_object; |
1434 | 1429 |
1435 if (!HasArgsInRegisters()) { | 1430 if (!HasArgsInRegisters()) { |
1436 __ lw(object, MemOperand(sp, 1 * kPointerSize)); | 1431 __ lw(object, MemOperand(sp, 1 * kPointerSize)); |
1437 __ lw(function, MemOperand(sp, 0)); | 1432 __ lw(function, MemOperand(sp, 0)); |
1438 } | 1433 } |
1439 | 1434 |
1440 // Check that the left hand is a JS object and load map. | 1435 // Check that the left hand is a JS object and load map. |
1441 __ JumpIfSmi(object, ¬_js_object); | 1436 __ JumpIfSmi(object, ¬_js_object); |
1442 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 1437 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); |
1443 | 1438 |
1444 // If there is a call site cache don't look in the global cache, but do the | 1439 // If there is a call site cache don't look in the global cache, but do the |
1445 // real lookup and update the call site cache. | 1440 // real lookup and update the call site cache. |
1446 if (!HasCallSiteInlineCheck()) { | 1441 if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) { |
1447 Label miss; | 1442 Label miss; |
1448 __ LoadRoot(at, Heap::kInstanceofCacheFunctionRootIndex); | 1443 __ LoadRoot(at, Heap::kInstanceofCacheFunctionRootIndex); |
1449 __ Branch(&miss, ne, function, Operand(at)); | 1444 __ Branch(&miss, ne, function, Operand(at)); |
1450 __ LoadRoot(at, Heap::kInstanceofCacheMapRootIndex); | 1445 __ LoadRoot(at, Heap::kInstanceofCacheMapRootIndex); |
1451 __ Branch(&miss, ne, map, Operand(at)); | 1446 __ Branch(&miss, ne, map, Operand(at)); |
1452 __ LoadRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); | 1447 __ LoadRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); |
1453 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); | 1448 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); |
1454 | 1449 |
1455 __ bind(&miss); | 1450 __ bind(&miss); |
1456 } | 1451 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1495 __ Branch(&is_not_instance, eq, scratch, Operand(scratch2)); | 1490 __ Branch(&is_not_instance, eq, scratch, Operand(scratch2)); |
1496 __ lw(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset)); | 1491 __ lw(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset)); |
1497 __ lw(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset)); | 1492 __ lw(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset)); |
1498 __ Branch(&loop); | 1493 __ Branch(&loop); |
1499 | 1494 |
1500 __ bind(&is_instance); | 1495 __ bind(&is_instance); |
1501 DCHECK(Smi::FromInt(0) == 0); | 1496 DCHECK(Smi::FromInt(0) == 0); |
1502 if (!HasCallSiteInlineCheck()) { | 1497 if (!HasCallSiteInlineCheck()) { |
1503 __ mov(v0, zero_reg); | 1498 __ mov(v0, zero_reg); |
1504 __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); | 1499 __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); |
| 1500 if (ReturnTrueFalseObject()) { |
| 1501 __ LoadRoot(v0, Heap::kTrueValueRootIndex); |
| 1502 } |
1505 } else { | 1503 } else { |
1506 // Patch the call site to return true. | 1504 // Patch the call site to return true. |
1507 __ LoadRoot(v0, Heap::kTrueValueRootIndex); | 1505 __ LoadRoot(v0, Heap::kTrueValueRootIndex); |
1508 __ Addu(inline_site, inline_site, Operand(kDeltaToLoadBoolResult)); | 1506 __ Addu(inline_site, inline_site, Operand(kDeltaToLoadBoolResult)); |
1509 // Get the boolean result location in scratch and patch it. | 1507 // Get the boolean result location in scratch and patch it. |
1510 __ PatchRelocatedValue(inline_site, scratch, v0); | 1508 __ PatchRelocatedValue(inline_site, scratch, v0); |
1511 | 1509 |
1512 if (!ReturnTrueFalseObject()) { | 1510 if (!ReturnTrueFalseObject()) { |
1513 DCHECK_EQ(Smi::FromInt(0), 0); | 1511 DCHECK_EQ(Smi::FromInt(0), 0); |
1514 __ mov(v0, zero_reg); | 1512 __ mov(v0, zero_reg); |
1515 } | 1513 } |
1516 } | 1514 } |
1517 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); | 1515 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); |
1518 | 1516 |
1519 __ bind(&is_not_instance); | 1517 __ bind(&is_not_instance); |
1520 if (!HasCallSiteInlineCheck()) { | 1518 if (!HasCallSiteInlineCheck()) { |
1521 __ li(v0, Operand(Smi::FromInt(1))); | 1519 __ li(v0, Operand(Smi::FromInt(1))); |
1522 __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); | 1520 __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); |
| 1521 if (ReturnTrueFalseObject()) { |
| 1522 __ LoadRoot(v0, Heap::kFalseValueRootIndex); |
| 1523 } |
1523 } else { | 1524 } else { |
1524 // Patch the call site to return false. | 1525 // Patch the call site to return false. |
1525 __ LoadRoot(v0, Heap::kFalseValueRootIndex); | 1526 __ LoadRoot(v0, Heap::kFalseValueRootIndex); |
1526 __ Addu(inline_site, inline_site, Operand(kDeltaToLoadBoolResult)); | 1527 __ Addu(inline_site, inline_site, Operand(kDeltaToLoadBoolResult)); |
1527 // Get the boolean result location in scratch and patch it. | 1528 // Get the boolean result location in scratch and patch it. |
1528 __ PatchRelocatedValue(inline_site, scratch, v0); | 1529 __ PatchRelocatedValue(inline_site, scratch, v0); |
1529 | 1530 |
1530 if (!ReturnTrueFalseObject()) { | 1531 if (!ReturnTrueFalseObject()) { |
1531 __ li(v0, Operand(Smi::FromInt(1))); | 1532 __ li(v0, Operand(Smi::FromInt(1))); |
1532 } | 1533 } |
1533 } | 1534 } |
1534 | 1535 |
1535 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); | 1536 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); |
1536 | 1537 |
1537 Label object_not_null, object_not_null_or_smi; | 1538 Label object_not_null, object_not_null_or_smi; |
1538 __ bind(¬_js_object); | 1539 __ bind(¬_js_object); |
1539 // Before null, smi and string value checks, check that the rhs is a function | 1540 // Before null, smi and string value checks, check that the rhs is a function |
1540 // as for a non-function rhs an exception needs to be thrown. | 1541 // as for a non-function rhs an exception needs to be thrown. |
1541 __ JumpIfSmi(function, &slow); | 1542 __ JumpIfSmi(function, &slow); |
1542 __ GetObjectType(function, scratch2, scratch); | 1543 __ GetObjectType(function, scratch2, scratch); |
1543 __ Branch(&slow, ne, scratch, Operand(JS_FUNCTION_TYPE)); | 1544 __ Branch(&slow, ne, scratch, Operand(JS_FUNCTION_TYPE)); |
1544 | 1545 |
1545 // Null is not instance of anything. | 1546 // Null is not instance of anything. |
1546 __ Branch(&object_not_null, | 1547 __ Branch(&object_not_null, |
1547 ne, | 1548 ne, |
1548 scratch, | 1549 scratch, |
1549 Operand(isolate()->factory()->null_value())); | 1550 Operand(isolate()->factory()->null_value())); |
1550 __ li(v0, Operand(Smi::FromInt(1))); | 1551 if (ReturnTrueFalseObject()) { |
| 1552 __ LoadRoot(v0, Heap::kFalseValueRootIndex); |
| 1553 } else { |
| 1554 __ li(v0, Operand(Smi::FromInt(1))); |
| 1555 } |
1551 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); | 1556 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); |
1552 | 1557 |
1553 __ bind(&object_not_null); | 1558 __ bind(&object_not_null); |
1554 // Smi values are not instances of anything. | 1559 // Smi values are not instances of anything. |
1555 __ JumpIfNotSmi(object, &object_not_null_or_smi); | 1560 __ JumpIfNotSmi(object, &object_not_null_or_smi); |
1556 __ li(v0, Operand(Smi::FromInt(1))); | 1561 if (ReturnTrueFalseObject()) { |
| 1562 __ LoadRoot(v0, Heap::kFalseValueRootIndex); |
| 1563 } else { |
| 1564 __ li(v0, Operand(Smi::FromInt(1))); |
| 1565 } |
1557 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); | 1566 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); |
1558 | 1567 |
1559 __ bind(&object_not_null_or_smi); | 1568 __ bind(&object_not_null_or_smi); |
1560 // String values are not instances of anything. | 1569 // String values are not instances of anything. |
1561 __ IsObjectJSStringType(object, scratch, &slow); | 1570 __ IsObjectJSStringType(object, scratch, &slow); |
1562 __ li(v0, Operand(Smi::FromInt(1))); | 1571 if (ReturnTrueFalseObject()) { |
| 1572 __ LoadRoot(v0, Heap::kFalseValueRootIndex); |
| 1573 } else { |
| 1574 __ li(v0, Operand(Smi::FromInt(1))); |
| 1575 } |
1563 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); | 1576 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); |
1564 | 1577 |
1565 // Slow-case. Tail call builtin. | 1578 // Slow-case. Tail call builtin. |
1566 __ bind(&slow); | 1579 __ bind(&slow); |
1567 if (!ReturnTrueFalseObject()) { | 1580 if (!ReturnTrueFalseObject()) { |
1568 if (HasArgsInRegisters()) { | 1581 if (HasArgsInRegisters()) { |
1569 __ Push(a0, a1); | 1582 __ Push(a0, a1); |
1570 } | 1583 } |
1571 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 1584 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
1572 } else { | 1585 } else { |
(...skipping 3312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4885 MemOperand(fp, 6 * kPointerSize), | 4898 MemOperand(fp, 6 * kPointerSize), |
4886 NULL); | 4899 NULL); |
4887 } | 4900 } |
4888 | 4901 |
4889 | 4902 |
4890 #undef __ | 4903 #undef __ |
4891 | 4904 |
4892 } } // namespace v8::internal | 4905 } } // namespace v8::internal |
4893 | 4906 |
4894 #endif // V8_TARGET_ARCH_MIPS | 4907 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |