OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 Label* rhs_not_nan, | 487 Label* rhs_not_nan, |
488 Label* slow, | 488 Label* slow, |
489 bool strict); | 489 bool strict); |
490 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, | 490 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, |
491 Register lhs, | 491 Register lhs, |
492 Register rhs); | 492 Register rhs); |
493 | 493 |
494 | 494 |
495 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { | 495 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { |
496 // Update the static counter each time a new code stub is generated. | 496 // Update the static counter each time a new code stub is generated. |
497 Isolate* isolate = masm->isolate(); | 497 isolate()->counters()->code_stubs()->Increment(); |
498 isolate->counters()->code_stubs()->Increment(); | |
499 | 498 |
500 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); | 499 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate()); |
501 int param_count = descriptor->register_param_count_; | 500 int param_count = descriptor->register_param_count_; |
502 { | 501 { |
503 // Call the runtime system in a fresh internal frame. | 502 // Call the runtime system in a fresh internal frame. |
504 FrameScope scope(masm, StackFrame::INTERNAL); | 503 FrameScope scope(masm, StackFrame::INTERNAL); |
505 ASSERT(descriptor->register_param_count_ == 0 || | 504 ASSERT(descriptor->register_param_count_ == 0 || |
506 a0.is(descriptor->register_params_[param_count - 1])); | 505 a0.is(descriptor->register_params_[param_count - 1])); |
507 // Push arguments, adjust sp. | 506 // Push arguments, adjust sp. |
508 __ Subu(sp, sp, Operand(param_count * kPointerSize)); | 507 __ Subu(sp, sp, Operand(param_count * kPointerSize)); |
509 for (int i = 0; i < param_count; ++i) { | 508 for (int i = 0; i < param_count; ++i) { |
510 // Store argument to stack. | 509 // Store argument to stack. |
511 __ sw(descriptor->register_params_[i], | 510 __ sw(descriptor->register_params_[i], |
512 MemOperand(sp, (param_count-1-i) * kPointerSize)); | 511 MemOperand(sp, (param_count-1-i) * kPointerSize)); |
513 } | 512 } |
514 ExternalReference miss = descriptor->miss_handler(); | 513 ExternalReference miss = descriptor->miss_handler(); |
515 __ CallExternalReference(miss, descriptor->register_param_count_); | 514 __ CallExternalReference(miss, descriptor->register_param_count_); |
516 } | 515 } |
517 | 516 |
518 __ Ret(); | 517 __ Ret(); |
519 } | 518 } |
520 | 519 |
521 | 520 |
522 // Takes a Smi and converts to an IEEE 64 bit floating point value in two | 521 // Takes a Smi and converts to an IEEE 64 bit floating point value in two |
523 // registers. The format is 1 sign bit, 11 exponent bits (biased 1023) and | 522 // registers. The format is 1 sign bit, 11 exponent bits (biased 1023) and |
524 // 52 fraction bits (20 in the first word, 32 in the second). Zeros is a | 523 // 52 fraction bits (20 in the first word, 32 in the second). Zeros is a |
525 // scratch register. Destroys the source register. No GC occurs during this | 524 // scratch register. Destroys the source register. No GC occurs during this |
526 // stub so you don't have to set up the frame. | 525 // stub so you don't have to set up the frame. |
527 class ConvertToDoubleStub : public PlatformCodeStub { | 526 class ConvertToDoubleStub : public PlatformCodeStub { |
528 public: | 527 public: |
529 ConvertToDoubleStub(Register result_reg_1, | 528 ConvertToDoubleStub(Isolate* isolate, |
| 529 Register result_reg_1, |
530 Register result_reg_2, | 530 Register result_reg_2, |
531 Register source_reg, | 531 Register source_reg, |
532 Register scratch_reg) | 532 Register scratch_reg) |
533 : result1_(result_reg_1), | 533 : PlatformCodeStub(isolate), |
| 534 result1_(result_reg_1), |
534 result2_(result_reg_2), | 535 result2_(result_reg_2), |
535 source_(source_reg), | 536 source_(source_reg), |
536 zeros_(scratch_reg) { } | 537 zeros_(scratch_reg) { } |
537 | 538 |
538 private: | 539 private: |
539 Register result1_; | 540 Register result1_; |
540 Register result2_; | 541 Register result2_; |
541 Register source_; | 542 Register source_; |
542 Register zeros_; | 543 Register zeros_; |
543 | 544 |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 | 755 |
755 __ bind(&done); | 756 __ bind(&done); |
756 | 757 |
757 __ Pop(scratch, scratch2, scratch3); | 758 __ Pop(scratch, scratch2, scratch3); |
758 __ Ret(); | 759 __ Ret(); |
759 } | 760 } |
760 | 761 |
761 | 762 |
762 void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime( | 763 void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime( |
763 Isolate* isolate) { | 764 Isolate* isolate) { |
764 WriteInt32ToHeapNumberStub stub1(a1, v0, a2, a3); | 765 WriteInt32ToHeapNumberStub stub1(isolate, a1, v0, a2, a3); |
765 WriteInt32ToHeapNumberStub stub2(a2, v0, a3, a0); | 766 WriteInt32ToHeapNumberStub stub2(isolate, a2, v0, a3, a0); |
766 stub1.GetCode(isolate); | 767 stub1.GetCode(isolate); |
767 stub2.GetCode(isolate); | 768 stub2.GetCode(isolate); |
768 } | 769 } |
769 | 770 |
770 | 771 |
771 // See comment for class, this does NOT work for int32's that are in Smi range. | 772 // See comment for class, this does NOT work for int32's that are in Smi range. |
772 void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { | 773 void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { |
773 Label max_negative_int; | 774 Label max_negative_int; |
774 // the_int_ has the answer which is a signed int32 but not a Smi. | 775 // the_int_ has the answer which is a signed int32 but not a Smi. |
775 // We test for the special value that has a different exponent. | 776 // We test for the special value that has a different exponent. |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1147 // In cases 3 and 4 we have found out we were dealing with a number-number | 1148 // In cases 3 and 4 we have found out we were dealing with a number-number |
1148 // comparison and the numbers have been loaded into f12 and f14 as doubles, | 1149 // comparison and the numbers have been loaded into f12 and f14 as doubles, |
1149 // or in GP registers (a0, a1, a2, a3) depending on the presence of the FPU. | 1150 // or in GP registers (a0, a1, a2, a3) depending on the presence of the FPU. |
1150 EmitSmiNonsmiComparison(masm, lhs, rhs, | 1151 EmitSmiNonsmiComparison(masm, lhs, rhs, |
1151 &both_loaded_as_doubles, &slow, strict()); | 1152 &both_loaded_as_doubles, &slow, strict()); |
1152 | 1153 |
1153 __ bind(&both_loaded_as_doubles); | 1154 __ bind(&both_loaded_as_doubles); |
1154 // f12, f14 are the double representations of the left hand side | 1155 // f12, f14 are the double representations of the left hand side |
1155 // and the right hand side if we have FPU. Otherwise a2, a3 represent | 1156 // and the right hand side if we have FPU. Otherwise a2, a3 represent |
1156 // left hand side and a0, a1 represent right hand side. | 1157 // left hand side and a0, a1 represent right hand side. |
1157 | |
1158 Isolate* isolate = masm->isolate(); | |
1159 Label nan; | 1158 Label nan; |
1160 __ li(t0, Operand(LESS)); | 1159 __ li(t0, Operand(LESS)); |
1161 __ li(t1, Operand(GREATER)); | 1160 __ li(t1, Operand(GREATER)); |
1162 __ li(t2, Operand(EQUAL)); | 1161 __ li(t2, Operand(EQUAL)); |
1163 | 1162 |
1164 // Check if either rhs or lhs is NaN. | 1163 // Check if either rhs or lhs is NaN. |
1165 __ BranchF(NULL, &nan, eq, f12, f14); | 1164 __ BranchF(NULL, &nan, eq, f12, f14); |
1166 | 1165 |
1167 // Check if LESS condition is satisfied. If true, move conditionally | 1166 // Check if LESS condition is satisfied. If true, move conditionally |
1168 // result to v0. | 1167 // result to v0. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1223 EmitCheckForInternalizedStringsOrObjects( | 1222 EmitCheckForInternalizedStringsOrObjects( |
1224 masm, lhs, rhs, &flat_string_check, &slow); | 1223 masm, lhs, rhs, &flat_string_check, &slow); |
1225 } | 1224 } |
1226 | 1225 |
1227 // Check for both being sequential ASCII strings, and inline if that is the | 1226 // Check for both being sequential ASCII strings, and inline if that is the |
1228 // case. | 1227 // case. |
1229 __ bind(&flat_string_check); | 1228 __ bind(&flat_string_check); |
1230 | 1229 |
1231 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, a2, a3, &slow); | 1230 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, a2, a3, &slow); |
1232 | 1231 |
1233 __ IncrementCounter(isolate->counters()->string_compare_native(), 1, a2, a3); | 1232 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, a2, |
| 1233 a3); |
1234 if (cc == eq) { | 1234 if (cc == eq) { |
1235 StringCompareStub::GenerateFlatAsciiStringEquals(masm, | 1235 StringCompareStub::GenerateFlatAsciiStringEquals(masm, |
1236 lhs, | 1236 lhs, |
1237 rhs, | 1237 rhs, |
1238 a2, | 1238 a2, |
1239 a3, | 1239 a3, |
1240 t0); | 1240 t0); |
1241 } else { | 1241 } else { |
1242 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, | 1242 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, |
1243 lhs, | 1243 lhs, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1311 __ MultiPush(kJSCallerSaved | ra.bit()); | 1311 __ MultiPush(kJSCallerSaved | ra.bit()); |
1312 if (save_doubles_ == kSaveFPRegs) { | 1312 if (save_doubles_ == kSaveFPRegs) { |
1313 __ MultiPushFPU(kCallerSavedFPU); | 1313 __ MultiPushFPU(kCallerSavedFPU); |
1314 } | 1314 } |
1315 const int argument_count = 1; | 1315 const int argument_count = 1; |
1316 const int fp_argument_count = 0; | 1316 const int fp_argument_count = 0; |
1317 const Register scratch = a1; | 1317 const Register scratch = a1; |
1318 | 1318 |
1319 AllowExternalCallThatCantCauseGC scope(masm); | 1319 AllowExternalCallThatCantCauseGC scope(masm); |
1320 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); | 1320 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); |
1321 __ li(a0, Operand(ExternalReference::isolate_address(masm->isolate()))); | 1321 __ li(a0, Operand(ExternalReference::isolate_address(isolate()))); |
1322 __ CallCFunction( | 1322 __ CallCFunction( |
1323 ExternalReference::store_buffer_overflow_function(masm->isolate()), | 1323 ExternalReference::store_buffer_overflow_function(isolate()), |
1324 argument_count); | 1324 argument_count); |
1325 if (save_doubles_ == kSaveFPRegs) { | 1325 if (save_doubles_ == kSaveFPRegs) { |
1326 __ MultiPopFPU(kCallerSavedFPU); | 1326 __ MultiPopFPU(kCallerSavedFPU); |
1327 } | 1327 } |
1328 | 1328 |
1329 __ MultiPop(kJSCallerSaved | ra.bit()); | 1329 __ MultiPop(kJSCallerSaved | ra.bit()); |
1330 __ Ret(); | 1330 __ Ret(); |
1331 } | 1331 } |
1332 | 1332 |
1333 | 1333 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1442 __ div_d(double_result, double_result, double_scratch); | 1442 __ div_d(double_result, double_result, double_scratch); |
1443 __ jmp(&done); | 1443 __ jmp(&done); |
1444 } | 1444 } |
1445 | 1445 |
1446 __ push(ra); | 1446 __ push(ra); |
1447 { | 1447 { |
1448 AllowExternalCallThatCantCauseGC scope(masm); | 1448 AllowExternalCallThatCantCauseGC scope(masm); |
1449 __ PrepareCallCFunction(0, 2, scratch2); | 1449 __ PrepareCallCFunction(0, 2, scratch2); |
1450 __ MovToFloatParameters(double_base, double_exponent); | 1450 __ MovToFloatParameters(double_base, double_exponent); |
1451 __ CallCFunction( | 1451 __ CallCFunction( |
1452 ExternalReference::power_double_double_function(masm->isolate()), | 1452 ExternalReference::power_double_double_function(isolate()), |
1453 0, 2); | 1453 0, 2); |
1454 } | 1454 } |
1455 __ pop(ra); | 1455 __ pop(ra); |
1456 __ MovFromFloatResult(double_result); | 1456 __ MovFromFloatResult(double_result); |
1457 __ jmp(&done); | 1457 __ jmp(&done); |
1458 | 1458 |
1459 __ bind(&int_exponent_convert); | 1459 __ bind(&int_exponent_convert); |
1460 } | 1460 } |
1461 | 1461 |
1462 // Calculate power with integer exponent. | 1462 // Calculate power with integer exponent. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1503 // Test whether result is zero. Bail out to check for subnormal result. | 1503 // Test whether result is zero. Bail out to check for subnormal result. |
1504 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 1504 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
1505 __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); | 1505 __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); |
1506 | 1506 |
1507 // double_exponent may not contain the exponent value if the input was a | 1507 // double_exponent may not contain the exponent value if the input was a |
1508 // smi. We set it with exponent value before bailing out. | 1508 // smi. We set it with exponent value before bailing out. |
1509 __ mtc1(exponent, single_scratch); | 1509 __ mtc1(exponent, single_scratch); |
1510 __ cvt_d_w(double_exponent, single_scratch); | 1510 __ cvt_d_w(double_exponent, single_scratch); |
1511 | 1511 |
1512 // Returning or bailing out. | 1512 // Returning or bailing out. |
1513 Counters* counters = masm->isolate()->counters(); | 1513 Counters* counters = isolate()->counters(); |
1514 if (exponent_type_ == ON_STACK) { | 1514 if (exponent_type_ == ON_STACK) { |
1515 // The arguments are still on the stack. | 1515 // The arguments are still on the stack. |
1516 __ bind(&call_runtime); | 1516 __ bind(&call_runtime); |
1517 __ TailCallRuntime(Runtime::kHiddenMathPow, 2, 1); | 1517 __ TailCallRuntime(Runtime::kHiddenMathPow, 2, 1); |
1518 | 1518 |
1519 // The stub is called from non-optimized code, which expects the result | 1519 // The stub is called from non-optimized code, which expects the result |
1520 // as heap number in exponent. | 1520 // as heap number in exponent. |
1521 __ bind(&done); | 1521 __ bind(&done); |
1522 __ AllocateHeapNumber( | 1522 __ AllocateHeapNumber( |
1523 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); | 1523 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); |
1524 __ sdc1(double_result, | 1524 __ sdc1(double_result, |
1525 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); | 1525 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); |
1526 ASSERT(heapnumber.is(v0)); | 1526 ASSERT(heapnumber.is(v0)); |
1527 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); | 1527 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); |
1528 __ DropAndRet(2); | 1528 __ DropAndRet(2); |
1529 } else { | 1529 } else { |
1530 __ push(ra); | 1530 __ push(ra); |
1531 { | 1531 { |
1532 AllowExternalCallThatCantCauseGC scope(masm); | 1532 AllowExternalCallThatCantCauseGC scope(masm); |
1533 __ PrepareCallCFunction(0, 2, scratch); | 1533 __ PrepareCallCFunction(0, 2, scratch); |
1534 __ MovToFloatParameters(double_base, double_exponent); | 1534 __ MovToFloatParameters(double_base, double_exponent); |
1535 __ CallCFunction( | 1535 __ CallCFunction( |
1536 ExternalReference::power_double_double_function(masm->isolate()), | 1536 ExternalReference::power_double_double_function(isolate()), |
1537 0, 2); | 1537 0, 2); |
1538 } | 1538 } |
1539 __ pop(ra); | 1539 __ pop(ra); |
1540 __ MovFromFloatResult(double_result); | 1540 __ MovFromFloatResult(double_result); |
1541 | 1541 |
1542 __ bind(&done); | 1542 __ bind(&done); |
1543 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); | 1543 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); |
1544 __ Ret(); | 1544 __ Ret(); |
1545 } | 1545 } |
1546 } | 1546 } |
(...skipping 13 matching lines...) Expand all Loading... |
1560 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); | 1560 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); |
1561 BinaryOpICStub::GenerateAheadOfTime(isolate); | 1561 BinaryOpICStub::GenerateAheadOfTime(isolate); |
1562 StoreRegistersStateStub::GenerateAheadOfTime(isolate); | 1562 StoreRegistersStateStub::GenerateAheadOfTime(isolate); |
1563 RestoreRegistersStateStub::GenerateAheadOfTime(isolate); | 1563 RestoreRegistersStateStub::GenerateAheadOfTime(isolate); |
1564 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); | 1564 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); |
1565 } | 1565 } |
1566 | 1566 |
1567 | 1567 |
1568 void StoreRegistersStateStub::GenerateAheadOfTime( | 1568 void StoreRegistersStateStub::GenerateAheadOfTime( |
1569 Isolate* isolate) { | 1569 Isolate* isolate) { |
1570 StoreRegistersStateStub stub1(kDontSaveFPRegs); | 1570 StoreRegistersStateStub stub1(isolate, kDontSaveFPRegs); |
1571 stub1.GetCode(isolate); | 1571 stub1.GetCode(isolate); |
1572 // Hydrogen code stubs need stub2 at snapshot time. | 1572 // Hydrogen code stubs need stub2 at snapshot time. |
1573 StoreRegistersStateStub stub2(kSaveFPRegs); | 1573 StoreRegistersStateStub stub2(isolate, kSaveFPRegs); |
1574 stub2.GetCode(isolate); | 1574 stub2.GetCode(isolate); |
1575 } | 1575 } |
1576 | 1576 |
1577 | 1577 |
1578 void RestoreRegistersStateStub::GenerateAheadOfTime( | 1578 void RestoreRegistersStateStub::GenerateAheadOfTime( |
1579 Isolate* isolate) { | 1579 Isolate* isolate) { |
1580 RestoreRegistersStateStub stub1(kDontSaveFPRegs); | 1580 RestoreRegistersStateStub stub1(isolate, kDontSaveFPRegs); |
1581 stub1.GetCode(isolate); | 1581 stub1.GetCode(isolate); |
1582 // Hydrogen code stubs need stub2 at snapshot time. | 1582 // Hydrogen code stubs need stub2 at snapshot time. |
1583 RestoreRegistersStateStub stub2(kSaveFPRegs); | 1583 RestoreRegistersStateStub stub2(isolate, kSaveFPRegs); |
1584 stub2.GetCode(isolate); | 1584 stub2.GetCode(isolate); |
1585 } | 1585 } |
1586 | 1586 |
1587 | 1587 |
1588 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 1588 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
1589 SaveFPRegsMode mode = kSaveFPRegs; | 1589 SaveFPRegsMode mode = kSaveFPRegs; |
1590 CEntryStub save_doubles(1, mode); | 1590 CEntryStub save_doubles(isolate, 1, mode); |
1591 StoreBufferOverflowStub stub(mode); | 1591 StoreBufferOverflowStub stub(isolate, mode); |
1592 // These stubs might already be in the snapshot, detect that and don't | 1592 // These stubs might already be in the snapshot, detect that and don't |
1593 // regenerate, which would lead to code stub initialization state being messed | 1593 // regenerate, which would lead to code stub initialization state being messed |
1594 // up. | 1594 // up. |
1595 Code* save_doubles_code; | 1595 Code* save_doubles_code; |
1596 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { | 1596 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { |
1597 save_doubles_code = *save_doubles.GetCode(isolate); | 1597 save_doubles_code = *save_doubles.GetCode(isolate); |
1598 } | 1598 } |
1599 Code* store_buffer_overflow_code; | 1599 Code* store_buffer_overflow_code; |
1600 if (!stub.FindCodeInCache(&store_buffer_overflow_code, isolate)) { | 1600 if (!stub.FindCodeInCache(&store_buffer_overflow_code, isolate)) { |
1601 store_buffer_overflow_code = *stub.GetCode(isolate); | 1601 store_buffer_overflow_code = *stub.GetCode(isolate); |
1602 } | 1602 } |
1603 isolate->set_fp_stubs_generated(true); | 1603 isolate->set_fp_stubs_generated(true); |
1604 } | 1604 } |
1605 | 1605 |
1606 | 1606 |
1607 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { | 1607 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { |
1608 CEntryStub stub(1, kDontSaveFPRegs); | 1608 CEntryStub stub(isolate, 1, kDontSaveFPRegs); |
1609 stub.GetCode(isolate); | 1609 stub.GetCode(isolate); |
1610 } | 1610 } |
1611 | 1611 |
1612 | 1612 |
1613 void CEntryStub::Generate(MacroAssembler* masm) { | 1613 void CEntryStub::Generate(MacroAssembler* masm) { |
1614 // Called from JavaScript; parameters are on stack as if calling JS function | 1614 // Called from JavaScript; parameters are on stack as if calling JS function |
1615 // s0: number of arguments including receiver | 1615 // s0: number of arguments including receiver |
1616 // s1: size of arguments excluding receiver | 1616 // s1: size of arguments excluding receiver |
1617 // s2: pointer to builtin function | 1617 // s2: pointer to builtin function |
1618 // fp: frame pointer (restored after C call) | 1618 // fp: frame pointer (restored after C call) |
(...skipping 11 matching lines...) Expand all Loading... |
1630 __ Addu(s1, sp, s1); | 1630 __ Addu(s1, sp, s1); |
1631 | 1631 |
1632 // Enter the exit frame that transitions from JavaScript to C++. | 1632 // Enter the exit frame that transitions from JavaScript to C++. |
1633 FrameScope scope(masm, StackFrame::MANUAL); | 1633 FrameScope scope(masm, StackFrame::MANUAL); |
1634 __ EnterExitFrame(save_doubles_); | 1634 __ EnterExitFrame(save_doubles_); |
1635 | 1635 |
1636 // s0: number of arguments including receiver (C callee-saved) | 1636 // s0: number of arguments including receiver (C callee-saved) |
1637 // s1: pointer to first argument (C callee-saved) | 1637 // s1: pointer to first argument (C callee-saved) |
1638 // s2: pointer to builtin function (C callee-saved) | 1638 // s2: pointer to builtin function (C callee-saved) |
1639 | 1639 |
1640 Isolate* isolate = masm->isolate(); | |
1641 | |
1642 // Prepare arguments for C routine. | 1640 // Prepare arguments for C routine. |
1643 // a0 = argc | 1641 // a0 = argc |
1644 __ mov(a0, s0); | 1642 __ mov(a0, s0); |
1645 // a1 = argv (set in the delay slot after find_ra below). | 1643 // a1 = argv (set in the delay slot after find_ra below). |
1646 | 1644 |
1647 // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We | 1645 // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We |
1648 // also need to reserve the 4 argument slots on the stack. | 1646 // also need to reserve the 4 argument slots on the stack. |
1649 | 1647 |
1650 __ AssertStackIsAligned(); | 1648 __ AssertStackIsAligned(); |
1651 | 1649 |
1652 __ li(a2, Operand(ExternalReference::isolate_address(isolate))); | 1650 __ li(a2, Operand(ExternalReference::isolate_address(isolate()))); |
1653 | 1651 |
1654 // To let the GC traverse the return address of the exit frames, we need to | 1652 // To let the GC traverse the return address of the exit frames, we need to |
1655 // know where the return address is. The CEntryStub is unmovable, so | 1653 // know where the return address is. The CEntryStub is unmovable, so |
1656 // we can store the address on the stack to be able to find it again and | 1654 // we can store the address on the stack to be able to find it again and |
1657 // we never have to restore it, because it will not change. | 1655 // we never have to restore it, because it will not change. |
1658 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); | 1656 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); |
1659 // This branch-and-link sequence is needed to find the current PC on mips, | 1657 // This branch-and-link sequence is needed to find the current PC on mips, |
1660 // saved to the ra register. | 1658 // saved to the ra register. |
1661 // Use masm-> here instead of the double-underscore macro since extra | 1659 // Use masm-> here instead of the double-underscore macro since extra |
1662 // coverage code can interfere with the proper calculation of ra. | 1660 // coverage code can interfere with the proper calculation of ra. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1694 __ stop("The hole escaped"); | 1692 __ stop("The hole escaped"); |
1695 __ bind(&okay); | 1693 __ bind(&okay); |
1696 } | 1694 } |
1697 | 1695 |
1698 // Check result for exception sentinel. | 1696 // Check result for exception sentinel. |
1699 Label exception_returned; | 1697 Label exception_returned; |
1700 __ LoadRoot(t0, Heap::kExceptionRootIndex); | 1698 __ LoadRoot(t0, Heap::kExceptionRootIndex); |
1701 __ Branch(&exception_returned, eq, t0, Operand(v0)); | 1699 __ Branch(&exception_returned, eq, t0, Operand(v0)); |
1702 | 1700 |
1703 ExternalReference pending_exception_address( | 1701 ExternalReference pending_exception_address( |
1704 Isolate::kPendingExceptionAddress, isolate); | 1702 Isolate::kPendingExceptionAddress, isolate()); |
1705 | 1703 |
1706 // Check that there is no pending exception, otherwise we | 1704 // Check that there is no pending exception, otherwise we |
1707 // should have returned the exception sentinel. | 1705 // should have returned the exception sentinel. |
1708 if (FLAG_debug_code) { | 1706 if (FLAG_debug_code) { |
1709 Label okay; | 1707 Label okay; |
1710 __ li(a2, Operand(pending_exception_address)); | 1708 __ li(a2, Operand(pending_exception_address)); |
1711 __ lw(a2, MemOperand(a2)); | 1709 __ lw(a2, MemOperand(a2)); |
1712 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 1710 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
1713 // Cannot use check here as it attempts to generate call into runtime. | 1711 // Cannot use check here as it attempts to generate call into runtime. |
1714 __ Branch(&okay, eq, t0, Operand(a2)); | 1712 __ Branch(&okay, eq, t0, Operand(a2)); |
1715 __ stop("Unexpected pending exception"); | 1713 __ stop("Unexpected pending exception"); |
1716 __ bind(&okay); | 1714 __ bind(&okay); |
1717 } | 1715 } |
1718 | 1716 |
1719 // Exit C frame and return. | 1717 // Exit C frame and return. |
1720 // v0:v1: result | 1718 // v0:v1: result |
1721 // sp: stack pointer | 1719 // sp: stack pointer |
1722 // fp: frame pointer | 1720 // fp: frame pointer |
1723 // s0: still holds argc (callee-saved). | 1721 // s0: still holds argc (callee-saved). |
1724 __ LeaveExitFrame(save_doubles_, s0, true, EMIT_RETURN); | 1722 __ LeaveExitFrame(save_doubles_, s0, true, EMIT_RETURN); |
1725 | 1723 |
1726 // Handling of exception. | 1724 // Handling of exception. |
1727 __ bind(&exception_returned); | 1725 __ bind(&exception_returned); |
1728 | 1726 |
1729 // Retrieve the pending exception. | 1727 // Retrieve the pending exception. |
1730 __ li(a2, Operand(pending_exception_address)); | 1728 __ li(a2, Operand(pending_exception_address)); |
1731 __ lw(v0, MemOperand(a2)); | 1729 __ lw(v0, MemOperand(a2)); |
1732 | 1730 |
1733 // Clear the pending exception. | 1731 // Clear the pending exception. |
1734 __ li(a3, Operand(isolate->factory()->the_hole_value())); | 1732 __ li(a3, Operand(isolate()->factory()->the_hole_value())); |
1735 __ sw(a3, MemOperand(a2)); | 1733 __ sw(a3, MemOperand(a2)); |
1736 | 1734 |
1737 // Special handling of termination exceptions which are uncatchable | 1735 // Special handling of termination exceptions which are uncatchable |
1738 // by javascript code. | 1736 // by javascript code. |
1739 Label throw_termination_exception; | 1737 Label throw_termination_exception; |
1740 __ LoadRoot(t0, Heap::kTerminationExceptionRootIndex); | 1738 __ LoadRoot(t0, Heap::kTerminationExceptionRootIndex); |
1741 __ Branch(&throw_termination_exception, eq, v0, Operand(t0)); | 1739 __ Branch(&throw_termination_exception, eq, v0, Operand(t0)); |
1742 | 1740 |
1743 // Handle normal exception. | 1741 // Handle normal exception. |
1744 __ Throw(v0); | 1742 __ Throw(v0); |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2054 // Before null, smi and string value checks, check that the rhs is a function | 2052 // Before null, smi and string value checks, check that the rhs is a function |
2055 // as for a non-function rhs an exception needs to be thrown. | 2053 // as for a non-function rhs an exception needs to be thrown. |
2056 __ JumpIfSmi(function, &slow); | 2054 __ JumpIfSmi(function, &slow); |
2057 __ GetObjectType(function, scratch2, scratch); | 2055 __ GetObjectType(function, scratch2, scratch); |
2058 __ Branch(&slow, ne, scratch, Operand(JS_FUNCTION_TYPE)); | 2056 __ Branch(&slow, ne, scratch, Operand(JS_FUNCTION_TYPE)); |
2059 | 2057 |
2060 // Null is not instance of anything. | 2058 // Null is not instance of anything. |
2061 __ Branch(&object_not_null, | 2059 __ Branch(&object_not_null, |
2062 ne, | 2060 ne, |
2063 scratch, | 2061 scratch, |
2064 Operand(masm->isolate()->factory()->null_value())); | 2062 Operand(isolate()->factory()->null_value())); |
2065 __ li(v0, Operand(Smi::FromInt(1))); | 2063 __ li(v0, Operand(Smi::FromInt(1))); |
2066 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); | 2064 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); |
2067 | 2065 |
2068 __ bind(&object_not_null); | 2066 __ bind(&object_not_null); |
2069 // Smi values are not instances of anything. | 2067 // Smi values are not instances of anything. |
2070 __ JumpIfNotSmi(object, &object_not_null_or_smi); | 2068 __ JumpIfNotSmi(object, &object_not_null_or_smi); |
2071 __ li(v0, Operand(Smi::FromInt(1))); | 2069 __ li(v0, Operand(Smi::FromInt(1))); |
2072 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); | 2070 __ DropAndRet(HasArgsInRegisters() ? 0 : 2); |
2073 | 2071 |
2074 __ bind(&object_not_null_or_smi); | 2072 __ bind(&object_not_null_or_smi); |
(...skipping 27 matching lines...) Expand all Loading... |
2102 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { | 2100 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { |
2103 Label miss; | 2101 Label miss; |
2104 Register receiver; | 2102 Register receiver; |
2105 if (kind() == Code::KEYED_LOAD_IC) { | 2103 if (kind() == Code::KEYED_LOAD_IC) { |
2106 // ----------- S t a t e ------------- | 2104 // ----------- S t a t e ------------- |
2107 // -- ra : return address | 2105 // -- ra : return address |
2108 // -- a0 : key | 2106 // -- a0 : key |
2109 // -- a1 : receiver | 2107 // -- a1 : receiver |
2110 // ----------------------------------- | 2108 // ----------------------------------- |
2111 __ Branch(&miss, ne, a0, | 2109 __ Branch(&miss, ne, a0, |
2112 Operand(masm->isolate()->factory()->prototype_string())); | 2110 Operand(isolate()->factory()->prototype_string())); |
2113 receiver = a1; | 2111 receiver = a1; |
2114 } else { | 2112 } else { |
2115 ASSERT(kind() == Code::LOAD_IC); | 2113 ASSERT(kind() == Code::LOAD_IC); |
2116 // ----------- S t a t e ------------- | 2114 // ----------- S t a t e ------------- |
2117 // -- a2 : name | 2115 // -- a2 : name |
2118 // -- ra : return address | 2116 // -- ra : return address |
2119 // -- a0 : receiver | 2117 // -- a0 : receiver |
2120 // -- sp[0] : receiver | 2118 // -- sp[0] : receiver |
2121 // ----------------------------------- | 2119 // ----------------------------------- |
2122 receiver = a0; | 2120 receiver = a0; |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2543 // sp[0]: last_match_info (expected JSArray) | 2541 // sp[0]: last_match_info (expected JSArray) |
2544 // sp[4]: previous index | 2542 // sp[4]: previous index |
2545 // sp[8]: subject string | 2543 // sp[8]: subject string |
2546 // sp[12]: JSRegExp object | 2544 // sp[12]: JSRegExp object |
2547 | 2545 |
2548 const int kLastMatchInfoOffset = 0 * kPointerSize; | 2546 const int kLastMatchInfoOffset = 0 * kPointerSize; |
2549 const int kPreviousIndexOffset = 1 * kPointerSize; | 2547 const int kPreviousIndexOffset = 1 * kPointerSize; |
2550 const int kSubjectOffset = 2 * kPointerSize; | 2548 const int kSubjectOffset = 2 * kPointerSize; |
2551 const int kJSRegExpOffset = 3 * kPointerSize; | 2549 const int kJSRegExpOffset = 3 * kPointerSize; |
2552 | 2550 |
2553 Isolate* isolate = masm->isolate(); | |
2554 | |
2555 Label runtime; | 2551 Label runtime; |
2556 // Allocation of registers for this function. These are in callee save | 2552 // Allocation of registers for this function. These are in callee save |
2557 // registers and will be preserved by the call to the native RegExp code, as | 2553 // registers and will be preserved by the call to the native RegExp code, as |
2558 // this code is called using the normal C calling convention. When calling | 2554 // this code is called using the normal C calling convention. When calling |
2559 // directly from generated code the native RegExp code will not do a GC and | 2555 // directly from generated code the native RegExp code will not do a GC and |
2560 // therefore the content of these registers are safe to use after the call. | 2556 // therefore the content of these registers are safe to use after the call. |
2561 // MIPS - using s0..s2, since we are not using CEntry Stub. | 2557 // MIPS - using s0..s2, since we are not using CEntry Stub. |
2562 Register subject = s0; | 2558 Register subject = s0; |
2563 Register regexp_data = s1; | 2559 Register regexp_data = s1; |
2564 Register last_match_info_elements = s2; | 2560 Register last_match_info_elements = s2; |
2565 | 2561 |
2566 // Ensure that a RegExp stack is allocated. | 2562 // Ensure that a RegExp stack is allocated. |
2567 ExternalReference address_of_regexp_stack_memory_address = | 2563 ExternalReference address_of_regexp_stack_memory_address = |
2568 ExternalReference::address_of_regexp_stack_memory_address( | 2564 ExternalReference::address_of_regexp_stack_memory_address( |
2569 isolate); | 2565 isolate()); |
2570 ExternalReference address_of_regexp_stack_memory_size = | 2566 ExternalReference address_of_regexp_stack_memory_size = |
2571 ExternalReference::address_of_regexp_stack_memory_size(isolate); | 2567 ExternalReference::address_of_regexp_stack_memory_size(isolate()); |
2572 __ li(a0, Operand(address_of_regexp_stack_memory_size)); | 2568 __ li(a0, Operand(address_of_regexp_stack_memory_size)); |
2573 __ lw(a0, MemOperand(a0, 0)); | 2569 __ lw(a0, MemOperand(a0, 0)); |
2574 __ Branch(&runtime, eq, a0, Operand(zero_reg)); | 2570 __ Branch(&runtime, eq, a0, Operand(zero_reg)); |
2575 | 2571 |
2576 // Check that the first argument is a JSRegExp object. | 2572 // Check that the first argument is a JSRegExp object. |
2577 __ lw(a0, MemOperand(sp, kJSRegExpOffset)); | 2573 __ lw(a0, MemOperand(sp, kJSRegExpOffset)); |
2578 STATIC_ASSERT(kSmiTag == 0); | 2574 STATIC_ASSERT(kSmiTag == 0); |
2579 __ JumpIfSmi(a0, &runtime); | 2575 __ JumpIfSmi(a0, &runtime); |
2580 __ GetObjectType(a0, a1, a1); | 2576 __ GetObjectType(a0, a1, a1); |
2581 __ Branch(&runtime, ne, a1, Operand(JS_REGEXP_TYPE)); | 2577 __ Branch(&runtime, ne, a1, Operand(JS_REGEXP_TYPE)); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2708 // encoding. If it has, the field contains a code object otherwise it contains | 2704 // encoding. If it has, the field contains a code object otherwise it contains |
2709 // a smi (code flushing support). | 2705 // a smi (code flushing support). |
2710 __ JumpIfSmi(t9, &runtime); | 2706 __ JumpIfSmi(t9, &runtime); |
2711 | 2707 |
2712 // a1: previous index | 2708 // a1: previous index |
2713 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); | 2709 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); |
2714 // t9: code | 2710 // t9: code |
2715 // subject: Subject string | 2711 // subject: Subject string |
2716 // regexp_data: RegExp data (FixedArray) | 2712 // regexp_data: RegExp data (FixedArray) |
2717 // All checks done. Now push arguments for native regexp code. | 2713 // All checks done. Now push arguments for native regexp code. |
2718 __ IncrementCounter(isolate->counters()->regexp_entry_native(), | 2714 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), |
2719 1, a0, a2); | 2715 1, a0, a2); |
2720 | 2716 |
2721 // Isolates: note we add an additional parameter here (isolate pointer). | 2717 // Isolates: note we add an additional parameter here (isolate pointer). |
2722 const int kRegExpExecuteArguments = 9; | 2718 const int kRegExpExecuteArguments = 9; |
2723 const int kParameterRegisters = 4; | 2719 const int kParameterRegisters = 4; |
2724 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); | 2720 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); |
2725 | 2721 |
2726 // Stack pointer now points to cell where return address is to be written. | 2722 // Stack pointer now points to cell where return address is to be written. |
2727 // Arguments are before that on the stack or in registers, meaning we | 2723 // Arguments are before that on the stack or in registers, meaning we |
2728 // treat the return address as argument 5. Thus every argument after that | 2724 // treat the return address as argument 5. Thus every argument after that |
2729 // needs to be shifted back by 1. Since DirectCEntryStub will handle | 2725 // needs to be shifted back by 1. Since DirectCEntryStub will handle |
2730 // allocating space for the c argument slots, we don't need to calculate | 2726 // allocating space for the c argument slots, we don't need to calculate |
2731 // that into the argument positions on the stack. This is how the stack will | 2727 // that into the argument positions on the stack. This is how the stack will |
2732 // look (sp meaning the value of sp at this moment): | 2728 // look (sp meaning the value of sp at this moment): |
2733 // [sp + 5] - Argument 9 | 2729 // [sp + 5] - Argument 9 |
2734 // [sp + 4] - Argument 8 | 2730 // [sp + 4] - Argument 8 |
2735 // [sp + 3] - Argument 7 | 2731 // [sp + 3] - Argument 7 |
2736 // [sp + 2] - Argument 6 | 2732 // [sp + 2] - Argument 6 |
2737 // [sp + 1] - Argument 5 | 2733 // [sp + 1] - Argument 5 |
2738 // [sp + 0] - saved ra | 2734 // [sp + 0] - saved ra |
2739 | 2735 |
2740 // Argument 9: Pass current isolate address. | 2736 // Argument 9: Pass current isolate address. |
2741 // CFunctionArgumentOperand handles MIPS stack argument slots. | 2737 // CFunctionArgumentOperand handles MIPS stack argument slots. |
2742 __ li(a0, Operand(ExternalReference::isolate_address(isolate))); | 2738 __ li(a0, Operand(ExternalReference::isolate_address(isolate()))); |
2743 __ sw(a0, MemOperand(sp, 5 * kPointerSize)); | 2739 __ sw(a0, MemOperand(sp, 5 * kPointerSize)); |
2744 | 2740 |
2745 // Argument 8: Indicate that this is a direct call from JavaScript. | 2741 // Argument 8: Indicate that this is a direct call from JavaScript. |
2746 __ li(a0, Operand(1)); | 2742 __ li(a0, Operand(1)); |
2747 __ sw(a0, MemOperand(sp, 4 * kPointerSize)); | 2743 __ sw(a0, MemOperand(sp, 4 * kPointerSize)); |
2748 | 2744 |
2749 // Argument 7: Start (high end) of backtracking stack memory area. | 2745 // Argument 7: Start (high end) of backtracking stack memory area. |
2750 __ li(a0, Operand(address_of_regexp_stack_memory_address)); | 2746 __ li(a0, Operand(address_of_regexp_stack_memory_address)); |
2751 __ lw(a0, MemOperand(a0, 0)); | 2747 __ lw(a0, MemOperand(a0, 0)); |
2752 __ li(a2, Operand(address_of_regexp_stack_memory_size)); | 2748 __ li(a2, Operand(address_of_regexp_stack_memory_size)); |
2753 __ lw(a2, MemOperand(a2, 0)); | 2749 __ lw(a2, MemOperand(a2, 0)); |
2754 __ addu(a0, a0, a2); | 2750 __ addu(a0, a0, a2); |
2755 __ sw(a0, MemOperand(sp, 3 * kPointerSize)); | 2751 __ sw(a0, MemOperand(sp, 3 * kPointerSize)); |
2756 | 2752 |
2757 // Argument 6: Set the number of capture registers to zero to force global | 2753 // Argument 6: Set the number of capture registers to zero to force global |
2758 // regexps to behave as non-global. This does not affect non-global regexps. | 2754 // regexps to behave as non-global. This does not affect non-global regexps. |
2759 __ mov(a0, zero_reg); | 2755 __ mov(a0, zero_reg); |
2760 __ sw(a0, MemOperand(sp, 2 * kPointerSize)); | 2756 __ sw(a0, MemOperand(sp, 2 * kPointerSize)); |
2761 | 2757 |
2762 // Argument 5: static offsets vector buffer. | 2758 // Argument 5: static offsets vector buffer. |
2763 __ li(a0, Operand( | 2759 __ li(a0, Operand( |
2764 ExternalReference::address_of_static_offsets_vector(isolate))); | 2760 ExternalReference::address_of_static_offsets_vector(isolate()))); |
2765 __ sw(a0, MemOperand(sp, 1 * kPointerSize)); | 2761 __ sw(a0, MemOperand(sp, 1 * kPointerSize)); |
2766 | 2762 |
2767 // For arguments 4 and 3 get string length, calculate start of string data | 2763 // For arguments 4 and 3 get string length, calculate start of string data |
2768 // and calculate the shift of the index (0 for ASCII and 1 for two byte). | 2764 // and calculate the shift of the index (0 for ASCII and 1 for two byte). |
2769 __ Addu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); | 2765 __ Addu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); |
2770 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. | 2766 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. |
2771 // Load the length from the original subject string from the previous stack | 2767 // Load the length from the original subject string from the previous stack |
2772 // frame. Therefore we have to use fp, which points exactly to two pointer | 2768 // frame. Therefore we have to use fp, which points exactly to two pointer |
2773 // sizes below the previous sp. (Because creating a new stack frame pushes | 2769 // sizes below the previous sp. (Because creating a new stack frame pushes |
2774 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) | 2770 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) |
(...skipping 12 matching lines...) Expand all Loading... |
2787 __ sllv(t1, t2, a3); | 2783 __ sllv(t1, t2, a3); |
2788 __ addu(a3, t0, t1); | 2784 __ addu(a3, t0, t1); |
2789 // Argument 2 (a1): Previous index. | 2785 // Argument 2 (a1): Previous index. |
2790 // Already there | 2786 // Already there |
2791 | 2787 |
2792 // Argument 1 (a0): Subject string. | 2788 // Argument 1 (a0): Subject string. |
2793 __ mov(a0, subject); | 2789 __ mov(a0, subject); |
2794 | 2790 |
2795 // Locate the code entry and call it. | 2791 // Locate the code entry and call it. |
2796 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); | 2792 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); |
2797 DirectCEntryStub stub; | 2793 DirectCEntryStub stub(isolate()); |
2798 stub.GenerateCall(masm, t9); | 2794 stub.GenerateCall(masm, t9); |
2799 | 2795 |
2800 __ LeaveExitFrame(false, no_reg, true); | 2796 __ LeaveExitFrame(false, no_reg, true); |
2801 | 2797 |
2802 // v0: result | 2798 // v0: result |
2803 // subject: subject string (callee saved) | 2799 // subject: subject string (callee saved) |
2804 // regexp_data: RegExp data (callee saved) | 2800 // regexp_data: RegExp data (callee saved) |
2805 // last_match_info_elements: Last match info elements (callee saved) | 2801 // last_match_info_elements: Last match info elements (callee saved) |
2806 // Check the result. | 2802 // Check the result. |
2807 Label success; | 2803 Label success; |
2808 __ Branch(&success, eq, v0, Operand(1)); | 2804 __ Branch(&success, eq, v0, Operand(1)); |
2809 // We expect exactly one result since we force the called regexp to behave | 2805 // We expect exactly one result since we force the called regexp to behave |
2810 // as non-global. | 2806 // as non-global. |
2811 Label failure; | 2807 Label failure; |
2812 __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE)); | 2808 __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE)); |
2813 // If not exception it can only be retry. Handle that in the runtime system. | 2809 // If not exception it can only be retry. Handle that in the runtime system. |
2814 __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); | 2810 __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); |
2815 // Result must now be exception. If there is no pending exception already a | 2811 // Result must now be exception. If there is no pending exception already a |
2816 // stack overflow (on the backtrack stack) was detected in RegExp code but | 2812 // stack overflow (on the backtrack stack) was detected in RegExp code but |
2817 // haven't created the exception yet. Handle that in the runtime system. | 2813 // haven't created the exception yet. Handle that in the runtime system. |
2818 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 2814 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
2819 __ li(a1, Operand(isolate->factory()->the_hole_value())); | 2815 __ li(a1, Operand(isolate()->factory()->the_hole_value())); |
2820 __ li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, | 2816 __ li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, |
2821 isolate))); | 2817 isolate()))); |
2822 __ lw(v0, MemOperand(a2, 0)); | 2818 __ lw(v0, MemOperand(a2, 0)); |
2823 __ Branch(&runtime, eq, v0, Operand(a1)); | 2819 __ Branch(&runtime, eq, v0, Operand(a1)); |
2824 | 2820 |
2825 __ sw(a1, MemOperand(a2, 0)); // Clear pending exception. | 2821 __ sw(a1, MemOperand(a2, 0)); // Clear pending exception. |
2826 | 2822 |
2827 // Check if the exception is a termination. If so, throw as uncatchable. | 2823 // Check if the exception is a termination. If so, throw as uncatchable. |
2828 __ LoadRoot(a0, Heap::kTerminationExceptionRootIndex); | 2824 __ LoadRoot(a0, Heap::kTerminationExceptionRootIndex); |
2829 Label termination_exception; | 2825 Label termination_exception; |
2830 __ Branch(&termination_exception, eq, v0, Operand(a0)); | 2826 __ Branch(&termination_exception, eq, v0, Operand(a0)); |
2831 | 2827 |
2832 __ Throw(v0); | 2828 __ Throw(v0); |
2833 | 2829 |
2834 __ bind(&termination_exception); | 2830 __ bind(&termination_exception); |
2835 __ ThrowUncatchable(v0); | 2831 __ ThrowUncatchable(v0); |
2836 | 2832 |
2837 __ bind(&failure); | 2833 __ bind(&failure); |
2838 // For failure and exception return null. | 2834 // For failure and exception return null. |
2839 __ li(v0, Operand(isolate->factory()->null_value())); | 2835 __ li(v0, Operand(isolate()->factory()->null_value())); |
2840 __ DropAndRet(4); | 2836 __ DropAndRet(4); |
2841 | 2837 |
2842 // Process the result from the native regexp code. | 2838 // Process the result from the native regexp code. |
2843 __ bind(&success); | 2839 __ bind(&success); |
2844 __ lw(a1, | 2840 __ lw(a1, |
2845 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); | 2841 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); |
2846 // Calculate number of capture registers (number_of_captures + 1) * 2. | 2842 // Calculate number of capture registers (number_of_captures + 1) * 2. |
2847 // Multiplying by 2 comes for free since r1 is smi-tagged. | 2843 // Multiplying by 2 comes for free since r1 is smi-tagged. |
2848 STATIC_ASSERT(kSmiTag == 0); | 2844 STATIC_ASSERT(kSmiTag == 0); |
2849 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 2845 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2890 RegExpImpl::kLastInputOffset)); | 2886 RegExpImpl::kLastInputOffset)); |
2891 __ RecordWriteField(last_match_info_elements, | 2887 __ RecordWriteField(last_match_info_elements, |
2892 RegExpImpl::kLastInputOffset, | 2888 RegExpImpl::kLastInputOffset, |
2893 subject, | 2889 subject, |
2894 t3, | 2890 t3, |
2895 kRAHasNotBeenSaved, | 2891 kRAHasNotBeenSaved, |
2896 kDontSaveFPRegs); | 2892 kDontSaveFPRegs); |
2897 | 2893 |
2898 // Get the static offsets vector filled by the native regexp code. | 2894 // Get the static offsets vector filled by the native regexp code. |
2899 ExternalReference address_of_static_offsets_vector = | 2895 ExternalReference address_of_static_offsets_vector = |
2900 ExternalReference::address_of_static_offsets_vector(isolate); | 2896 ExternalReference::address_of_static_offsets_vector(isolate()); |
2901 __ li(a2, Operand(address_of_static_offsets_vector)); | 2897 __ li(a2, Operand(address_of_static_offsets_vector)); |
2902 | 2898 |
2903 // a1: number of capture registers | 2899 // a1: number of capture registers |
2904 // a2: offsets vector | 2900 // a2: offsets vector |
2905 Label next_capture, done; | 2901 Label next_capture, done; |
2906 // Capture register counter starts from number of capture registers and | 2902 // Capture register counter starts from number of capture registers and |
2907 // counts down until wrapping after zero. | 2903 // counts down until wrapping after zero. |
2908 __ Addu(a0, | 2904 __ Addu(a0, |
2909 last_match_info_elements, | 2905 last_match_info_elements, |
2910 Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag)); | 2906 Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag)); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3043 const RegList kSavedRegs = | 3039 const RegList kSavedRegs = |
3044 1 << 4 | // a0 | 3040 1 << 4 | // a0 |
3045 1 << 5 | // a1 | 3041 1 << 5 | // a1 |
3046 1 << 6 | // a2 | 3042 1 << 6 | // a2 |
3047 1 << 7; // a3 | 3043 1 << 7; // a3 |
3048 | 3044 |
3049 // Arguments register must be smi-tagged to call out. | 3045 // Arguments register must be smi-tagged to call out. |
3050 __ SmiTag(a0); | 3046 __ SmiTag(a0); |
3051 __ MultiPush(kSavedRegs); | 3047 __ MultiPush(kSavedRegs); |
3052 | 3048 |
3053 CreateAllocationSiteStub create_stub; | 3049 CreateAllocationSiteStub create_stub(masm->isolate()); |
3054 __ CallStub(&create_stub); | 3050 __ CallStub(&create_stub); |
3055 | 3051 |
3056 __ MultiPop(kSavedRegs); | 3052 __ MultiPop(kSavedRegs); |
3057 __ SmiUntag(a0); | 3053 __ SmiUntag(a0); |
3058 } | 3054 } |
3059 __ Branch(&done); | 3055 __ Branch(&done); |
3060 | 3056 |
3061 __ bind(¬_array_function); | 3057 __ bind(¬_array_function); |
3062 } | 3058 } |
3063 | 3059 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3131 } | 3127 } |
3132 __ InvokeFunction(a1, actual, JUMP_FUNCTION, NullCallWrapper()); | 3128 __ InvokeFunction(a1, actual, JUMP_FUNCTION, NullCallWrapper()); |
3133 | 3129 |
3134 if (NeedsChecks()) { | 3130 if (NeedsChecks()) { |
3135 // Slow-case: Non-function called. | 3131 // Slow-case: Non-function called. |
3136 __ bind(&slow); | 3132 __ bind(&slow); |
3137 if (RecordCallTarget()) { | 3133 if (RecordCallTarget()) { |
3138 // If there is a call target cache, mark it megamorphic in the | 3134 // If there is a call target cache, mark it megamorphic in the |
3139 // non-function case. MegamorphicSentinel is an immortal immovable | 3135 // non-function case. MegamorphicSentinel is an immortal immovable |
3140 // object (megamorphic symbol) so no write barrier is needed. | 3136 // object (megamorphic symbol) so no write barrier is needed. |
3141 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), | 3137 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(isolate()), |
3142 masm->isolate()->heap()->megamorphic_symbol()); | 3138 isolate()->heap()->megamorphic_symbol()); |
3143 __ sll(t1, a3, kPointerSizeLog2 - kSmiTagSize); | 3139 __ sll(t1, a3, kPointerSizeLog2 - kSmiTagSize); |
3144 __ Addu(t1, a2, Operand(t1)); | 3140 __ Addu(t1, a2, Operand(t1)); |
3145 __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex); | 3141 __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex); |
3146 __ sw(at, FieldMemOperand(t1, FixedArray::kHeaderSize)); | 3142 __ sw(at, FieldMemOperand(t1, FixedArray::kHeaderSize)); |
3147 } | 3143 } |
3148 // Check for function proxy. | 3144 // Check for function proxy. |
3149 __ Branch(&non_function, ne, t0, Operand(JS_FUNCTION_PROXY_TYPE)); | 3145 __ Branch(&non_function, ne, t0, Operand(JS_FUNCTION_PROXY_TYPE)); |
3150 __ push(a1); // Put proxy as additional argument. | 3146 __ push(a1); // Put proxy as additional argument. |
3151 __ li(a0, Operand(argc_ + 1, RelocInfo::NONE32)); | 3147 __ li(a0, Operand(argc_ + 1, RelocInfo::NONE32)); |
3152 __ li(a2, Operand(0, RelocInfo::NONE32)); | 3148 __ li(a2, Operand(0, RelocInfo::NONE32)); |
3153 __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY); | 3149 __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY); |
3154 { | 3150 { |
3155 Handle<Code> adaptor = | 3151 Handle<Code> adaptor = |
3156 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 3152 isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
3157 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3153 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
3158 } | 3154 } |
3159 | 3155 |
3160 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 3156 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
3161 // of the original receiver from the call site). | 3157 // of the original receiver from the call site). |
3162 __ bind(&non_function); | 3158 __ bind(&non_function); |
3163 __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); | 3159 __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); |
3164 __ li(a0, Operand(argc_)); // Set up the number of arguments. | 3160 __ li(a0, Operand(argc_)); // Set up the number of arguments. |
3165 __ li(a2, Operand(0, RelocInfo::NONE32)); | 3161 __ li(a2, Operand(0, RelocInfo::NONE32)); |
3166 __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION); | 3162 __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION); |
3167 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 3163 __ Jump(isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
3168 RelocInfo::CODE_TARGET); | 3164 RelocInfo::CODE_TARGET); |
3169 } | 3165 } |
3170 | 3166 |
3171 if (CallAsMethod()) { | 3167 if (CallAsMethod()) { |
3172 __ bind(&wrap); | 3168 __ bind(&wrap); |
3173 // Wrap the receiver and patch it back onto the stack. | 3169 // Wrap the receiver and patch it back onto the stack. |
3174 { FrameScope frame_scope(masm, StackFrame::INTERNAL); | 3170 { FrameScope frame_scope(masm, StackFrame::INTERNAL); |
3175 __ Push(a1, a3); | 3171 __ Push(a1, a3); |
3176 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 3172 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
3177 __ pop(a1); | 3173 __ pop(a1); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3235 __ bind(&slow); | 3231 __ bind(&slow); |
3236 __ Branch(&non_function_call, ne, t0, Operand(JS_FUNCTION_PROXY_TYPE)); | 3232 __ Branch(&non_function_call, ne, t0, Operand(JS_FUNCTION_PROXY_TYPE)); |
3237 __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); | 3233 __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
3238 __ jmp(&do_call); | 3234 __ jmp(&do_call); |
3239 | 3235 |
3240 __ bind(&non_function_call); | 3236 __ bind(&non_function_call); |
3241 __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | 3237 __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
3242 __ bind(&do_call); | 3238 __ bind(&do_call); |
3243 // Set expected number of arguments to zero (not changing r0). | 3239 // Set expected number of arguments to zero (not changing r0). |
3244 __ li(a2, Operand(0, RelocInfo::NONE32)); | 3240 __ li(a2, Operand(0, RelocInfo::NONE32)); |
3245 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 3241 __ Jump(isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
3246 RelocInfo::CODE_TARGET); | 3242 RelocInfo::CODE_TARGET); |
3247 } | 3243 } |
3248 | 3244 |
3249 | 3245 |
3250 // StringCharCodeAtGenerator. | 3246 // StringCharCodeAtGenerator. |
3251 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 3247 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
3252 Label flat_string; | 3248 Label flat_string; |
3253 Label ascii_string; | 3249 Label ascii_string; |
3254 Label got_char_code; | 3250 Label got_char_code; |
3255 Label sliced_string; | 3251 Label sliced_string; |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3763 | 3759 |
3764 // v0: result string. | 3760 // v0: result string. |
3765 // a1: first character of result. | 3761 // a1: first character of result. |
3766 // a2: result length. | 3762 // a2: result length. |
3767 // t1: first character of substring to copy. | 3763 // t1: first character of substring to copy. |
3768 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3764 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
3769 StringHelper::GenerateCopyCharactersLong( | 3765 StringHelper::GenerateCopyCharactersLong( |
3770 masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED); | 3766 masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED); |
3771 | 3767 |
3772 __ bind(&return_v0); | 3768 __ bind(&return_v0); |
3773 Counters* counters = masm->isolate()->counters(); | 3769 Counters* counters = isolate()->counters(); |
3774 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); | 3770 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); |
3775 __ DropAndRet(3); | 3771 __ DropAndRet(3); |
3776 | 3772 |
3777 // Just jump to runtime to create the sub string. | 3773 // Just jump to runtime to create the sub string. |
3778 __ bind(&runtime); | 3774 __ bind(&runtime); |
3779 __ TailCallRuntime(Runtime::kHiddenSubString, 3, 1); | 3775 __ TailCallRuntime(Runtime::kHiddenSubString, 3, 1); |
3780 | 3776 |
3781 __ bind(&single_char); | 3777 __ bind(&single_char); |
3782 // v0: original string | 3778 // v0: original string |
3783 // a1: instance type | 3779 // a1: instance type |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3907 __ lbu(scratch2, MemOperand(scratch3)); | 3903 __ lbu(scratch2, MemOperand(scratch3)); |
3908 __ Branch(chars_not_equal, ne, scratch1, Operand(scratch2)); | 3904 __ Branch(chars_not_equal, ne, scratch1, Operand(scratch2)); |
3909 __ Addu(index, index, 1); | 3905 __ Addu(index, index, 1); |
3910 __ Branch(&loop, ne, index, Operand(zero_reg)); | 3906 __ Branch(&loop, ne, index, Operand(zero_reg)); |
3911 } | 3907 } |
3912 | 3908 |
3913 | 3909 |
3914 void StringCompareStub::Generate(MacroAssembler* masm) { | 3910 void StringCompareStub::Generate(MacroAssembler* masm) { |
3915 Label runtime; | 3911 Label runtime; |
3916 | 3912 |
3917 Counters* counters = masm->isolate()->counters(); | 3913 Counters* counters = isolate()->counters(); |
3918 | 3914 |
3919 // Stack frame on entry. | 3915 // Stack frame on entry. |
3920 // sp[0]: right string | 3916 // sp[0]: right string |
3921 // sp[4]: left string | 3917 // sp[4]: left string |
3922 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); // Left. | 3918 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); // Left. |
3923 __ lw(a0, MemOperand(sp, 0 * kPointerSize)); // Right. | 3919 __ lw(a0, MemOperand(sp, 0 * kPointerSize)); // Right. |
3924 | 3920 |
3925 Label not_same; | 3921 Label not_same; |
3926 __ Branch(¬_same, ne, a0, Operand(a1)); | 3922 __ Branch(¬_same, ne, a0, Operand(a1)); |
3927 STATIC_ASSERT(EQUAL == 0); | 3923 STATIC_ASSERT(EQUAL == 0); |
(...skipping 16 matching lines...) Expand all Loading... |
3944 __ TailCallRuntime(Runtime::kHiddenStringCompare, 2, 1); | 3940 __ TailCallRuntime(Runtime::kHiddenStringCompare, 2, 1); |
3945 } | 3941 } |
3946 | 3942 |
3947 | 3943 |
3948 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 3944 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
3949 // ----------- S t a t e ------------- | 3945 // ----------- S t a t e ------------- |
3950 // -- a1 : left | 3946 // -- a1 : left |
3951 // -- a0 : right | 3947 // -- a0 : right |
3952 // -- ra : return address | 3948 // -- ra : return address |
3953 // ----------------------------------- | 3949 // ----------------------------------- |
3954 Isolate* isolate = masm->isolate(); | |
3955 | 3950 |
3956 // Load a2 with the allocation site. We stick an undefined dummy value here | 3951 // Load a2 with the allocation site. We stick an undefined dummy value here |
3957 // and replace it with the real allocation site later when we instantiate this | 3952 // and replace it with the real allocation site later when we instantiate this |
3958 // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). | 3953 // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). |
3959 __ li(a2, handle(isolate->heap()->undefined_value())); | 3954 __ li(a2, handle(isolate()->heap()->undefined_value())); |
3960 | 3955 |
3961 // Make sure that we actually patched the allocation site. | 3956 // Make sure that we actually patched the allocation site. |
3962 if (FLAG_debug_code) { | 3957 if (FLAG_debug_code) { |
3963 __ And(at, a2, Operand(kSmiTagMask)); | 3958 __ And(at, a2, Operand(kSmiTagMask)); |
3964 __ Assert(ne, kExpectedAllocationSite, at, Operand(zero_reg)); | 3959 __ Assert(ne, kExpectedAllocationSite, at, Operand(zero_reg)); |
3965 __ lw(t0, FieldMemOperand(a2, HeapObject::kMapOffset)); | 3960 __ lw(t0, FieldMemOperand(a2, HeapObject::kMapOffset)); |
3966 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); | 3961 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); |
3967 __ Assert(eq, kExpectedAllocationSite, t0, Operand(at)); | 3962 __ Assert(eq, kExpectedAllocationSite, t0, Operand(at)); |
3968 } | 3963 } |
3969 | 3964 |
3970 // Tail call into the stub that handles binary operations with allocation | 3965 // Tail call into the stub that handles binary operations with allocation |
3971 // sites. | 3966 // sites. |
3972 BinaryOpWithAllocationSiteStub stub(state_); | 3967 BinaryOpWithAllocationSiteStub stub(isolate(), state_); |
3973 __ TailCallStub(&stub); | 3968 __ TailCallStub(&stub); |
3974 } | 3969 } |
3975 | 3970 |
3976 | 3971 |
3977 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3972 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
3978 ASSERT(state_ == CompareIC::SMI); | 3973 ASSERT(state_ == CompareIC::SMI); |
3979 Label miss; | 3974 Label miss; |
3980 __ Or(a2, a1, a0); | 3975 __ Or(a2, a1, a0); |
3981 __ JumpIfNotSmi(a2, &miss); | 3976 __ JumpIfNotSmi(a2, &miss); |
3982 | 3977 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4058 __ bind(&fpu_eq); | 4053 __ bind(&fpu_eq); |
4059 __ Ret(USE_DELAY_SLOT); | 4054 __ Ret(USE_DELAY_SLOT); |
4060 __ li(v0, Operand(EQUAL)); | 4055 __ li(v0, Operand(EQUAL)); |
4061 | 4056 |
4062 __ bind(&fpu_lt); | 4057 __ bind(&fpu_lt); |
4063 __ Ret(USE_DELAY_SLOT); | 4058 __ Ret(USE_DELAY_SLOT); |
4064 __ li(v0, Operand(LESS)); | 4059 __ li(v0, Operand(LESS)); |
4065 | 4060 |
4066 __ bind(&unordered); | 4061 __ bind(&unordered); |
4067 __ bind(&generic_stub); | 4062 __ bind(&generic_stub); |
4068 ICCompareStub stub(op_, CompareIC::GENERIC, CompareIC::GENERIC, | 4063 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC, |
4069 CompareIC::GENERIC); | 4064 CompareIC::GENERIC); |
4070 __ Jump(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | 4065 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
4071 | 4066 |
4072 __ bind(&maybe_undefined1); | 4067 __ bind(&maybe_undefined1); |
4073 if (Token::IsOrderedRelationalCompareOp(op_)) { | 4068 if (Token::IsOrderedRelationalCompareOp(op_)) { |
4074 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 4069 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
4075 __ Branch(&miss, ne, a0, Operand(at)); | 4070 __ Branch(&miss, ne, a0, Operand(at)); |
4076 __ JumpIfSmi(a1, &unordered); | 4071 __ JumpIfSmi(a1, &unordered); |
4077 __ GetObjectType(a1, a2, a2); | 4072 __ GetObjectType(a1, a2, a2); |
4078 __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); | 4073 __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE)); |
4079 __ jmp(&unordered); | 4074 __ jmp(&unordered); |
4080 } | 4075 } |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4294 | 4289 |
4295 __ bind(&miss); | 4290 __ bind(&miss); |
4296 GenerateMiss(masm); | 4291 GenerateMiss(masm); |
4297 } | 4292 } |
4298 | 4293 |
4299 | 4294 |
4300 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 4295 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { |
4301 { | 4296 { |
4302 // Call the runtime system in a fresh internal frame. | 4297 // Call the runtime system in a fresh internal frame. |
4303 ExternalReference miss = | 4298 ExternalReference miss = |
4304 ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate()); | 4299 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); |
4305 FrameScope scope(masm, StackFrame::INTERNAL); | 4300 FrameScope scope(masm, StackFrame::INTERNAL); |
4306 __ Push(a1, a0); | 4301 __ Push(a1, a0); |
4307 __ Push(ra, a1, a0); | 4302 __ Push(ra, a1, a0); |
4308 __ li(t0, Operand(Smi::FromInt(op_))); | 4303 __ li(t0, Operand(Smi::FromInt(op_))); |
4309 __ addiu(sp, sp, -kPointerSize); | 4304 __ addiu(sp, sp, -kPointerSize); |
4310 __ CallExternalReference(miss, 3, USE_DELAY_SLOT); | 4305 __ CallExternalReference(miss, 3, USE_DELAY_SLOT); |
4311 __ sw(t0, MemOperand(sp)); // In the delay slot. | 4306 __ sw(t0, MemOperand(sp)); // In the delay slot. |
4312 // Compute the entry point of the rewritten stub. | 4307 // Compute the entry point of the rewritten stub. |
4313 __ Addu(a2, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); | 4308 __ Addu(a2, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); |
4314 // Restore registers. | 4309 // Restore registers. |
(...skipping 24 matching lines...) Expand all Loading... |
4339 __ Assert(ne, kReceivedInvalidReturnAddress, t0, | 4334 __ Assert(ne, kReceivedInvalidReturnAddress, t0, |
4340 Operand(reinterpret_cast<uint32_t>(kZapValue))); | 4335 Operand(reinterpret_cast<uint32_t>(kZapValue))); |
4341 } | 4336 } |
4342 __ Jump(t9); | 4337 __ Jump(t9); |
4343 } | 4338 } |
4344 | 4339 |
4345 | 4340 |
4346 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, | 4341 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, |
4347 Register target) { | 4342 Register target) { |
4348 intptr_t loc = | 4343 intptr_t loc = |
4349 reinterpret_cast<intptr_t>(GetCode(masm->isolate()).location()); | 4344 reinterpret_cast<intptr_t>(GetCode(isolate()).location()); |
4350 __ Move(t9, target); | 4345 __ Move(t9, target); |
4351 __ li(ra, Operand(loc, RelocInfo::CODE_TARGET), CONSTANT_SIZE); | 4346 __ li(ra, Operand(loc, RelocInfo::CODE_TARGET), CONSTANT_SIZE); |
4352 __ Call(ra); | 4347 __ Call(ra); |
4353 } | 4348 } |
4354 | 4349 |
4355 | 4350 |
4356 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, | 4351 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, |
4357 Label* miss, | 4352 Label* miss, |
4358 Label* done, | 4353 Label* done, |
4359 Register receiver, | 4354 Register receiver, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4414 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 4409 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
4415 } | 4410 } |
4416 | 4411 |
4417 const int spill_mask = | 4412 const int spill_mask = |
4418 (ra.bit() | t2.bit() | t1.bit() | t0.bit() | a3.bit() | | 4413 (ra.bit() | t2.bit() | t1.bit() | t0.bit() | a3.bit() | |
4419 a2.bit() | a1.bit() | a0.bit() | v0.bit()); | 4414 a2.bit() | a1.bit() | a0.bit() | v0.bit()); |
4420 | 4415 |
4421 __ MultiPush(spill_mask); | 4416 __ MultiPush(spill_mask); |
4422 __ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 4417 __ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
4423 __ li(a1, Operand(Handle<Name>(name))); | 4418 __ li(a1, Operand(Handle<Name>(name))); |
4424 NameDictionaryLookupStub stub(NEGATIVE_LOOKUP); | 4419 NameDictionaryLookupStub stub(masm->isolate(), NEGATIVE_LOOKUP); |
4425 __ CallStub(&stub); | 4420 __ CallStub(&stub); |
4426 __ mov(at, v0); | 4421 __ mov(at, v0); |
4427 __ MultiPop(spill_mask); | 4422 __ MultiPop(spill_mask); |
4428 | 4423 |
4429 __ Branch(done, eq, at, Operand(zero_reg)); | 4424 __ Branch(done, eq, at, Operand(zero_reg)); |
4430 __ Branch(miss, ne, at, Operand(zero_reg)); | 4425 __ Branch(miss, ne, at, Operand(zero_reg)); |
4431 } | 4426 } |
4432 | 4427 |
4433 | 4428 |
4434 // Probe the name dictionary in the |elements| register. Jump to the | 4429 // Probe the name dictionary in the |elements| register. Jump to the |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4493 | 4488 |
4494 __ MultiPush(spill_mask); | 4489 __ MultiPush(spill_mask); |
4495 if (name.is(a0)) { | 4490 if (name.is(a0)) { |
4496 ASSERT(!elements.is(a1)); | 4491 ASSERT(!elements.is(a1)); |
4497 __ Move(a1, name); | 4492 __ Move(a1, name); |
4498 __ Move(a0, elements); | 4493 __ Move(a0, elements); |
4499 } else { | 4494 } else { |
4500 __ Move(a0, elements); | 4495 __ Move(a0, elements); |
4501 __ Move(a1, name); | 4496 __ Move(a1, name); |
4502 } | 4497 } |
4503 NameDictionaryLookupStub stub(POSITIVE_LOOKUP); | 4498 NameDictionaryLookupStub stub(masm->isolate(), POSITIVE_LOOKUP); |
4504 __ CallStub(&stub); | 4499 __ CallStub(&stub); |
4505 __ mov(scratch2, a2); | 4500 __ mov(scratch2, a2); |
4506 __ mov(at, v0); | 4501 __ mov(at, v0); |
4507 __ MultiPop(spill_mask); | 4502 __ MultiPop(spill_mask); |
4508 | 4503 |
4509 __ Branch(done, ne, at, Operand(zero_reg)); | 4504 __ Branch(done, ne, at, Operand(zero_reg)); |
4510 __ Branch(miss, eq, at, Operand(zero_reg)); | 4505 __ Branch(miss, eq, at, Operand(zero_reg)); |
4511 } | 4506 } |
4512 | 4507 |
4513 | 4508 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4601 __ li(result, 1); | 4596 __ li(result, 1); |
4602 | 4597 |
4603 __ bind(¬_in_dictionary); | 4598 __ bind(¬_in_dictionary); |
4604 __ Ret(USE_DELAY_SLOT); | 4599 __ Ret(USE_DELAY_SLOT); |
4605 __ mov(result, zero_reg); | 4600 __ mov(result, zero_reg); |
4606 } | 4601 } |
4607 | 4602 |
4608 | 4603 |
4609 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( | 4604 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( |
4610 Isolate* isolate) { | 4605 Isolate* isolate) { |
4611 StoreBufferOverflowStub stub1(kDontSaveFPRegs); | 4606 StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs); |
4612 stub1.GetCode(isolate); | 4607 stub1.GetCode(isolate); |
4613 // Hydrogen code stubs need stub2 at snapshot time. | 4608 // Hydrogen code stubs need stub2 at snapshot time. |
4614 StoreBufferOverflowStub stub2(kSaveFPRegs); | 4609 StoreBufferOverflowStub stub2(isolate, kSaveFPRegs); |
4615 stub2.GetCode(isolate); | 4610 stub2.GetCode(isolate); |
4616 } | 4611 } |
4617 | 4612 |
4618 | 4613 |
4619 bool CodeStub::CanUseFPRegisters() { | 4614 bool CodeStub::CanUseFPRegisters() { |
4620 return true; // FPU is a base requirement for V8. | 4615 return true; // FPU is a base requirement for V8. |
4621 } | 4616 } |
4622 | 4617 |
4623 | 4618 |
4624 // Takes the input in 3 registers: address_ value_ and object_. A pointer to | 4619 // Takes the input in 3 registers: address_ value_ and object_. A pointer to |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4707 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); | 4702 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); |
4708 int argument_count = 3; | 4703 int argument_count = 3; |
4709 __ PrepareCallCFunction(argument_count, regs_.scratch0()); | 4704 __ PrepareCallCFunction(argument_count, regs_.scratch0()); |
4710 Register address = | 4705 Register address = |
4711 a0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); | 4706 a0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); |
4712 ASSERT(!address.is(regs_.object())); | 4707 ASSERT(!address.is(regs_.object())); |
4713 ASSERT(!address.is(a0)); | 4708 ASSERT(!address.is(a0)); |
4714 __ Move(address, regs_.address()); | 4709 __ Move(address, regs_.address()); |
4715 __ Move(a0, regs_.object()); | 4710 __ Move(a0, regs_.object()); |
4716 __ Move(a1, address); | 4711 __ Move(a1, address); |
4717 __ li(a2, Operand(ExternalReference::isolate_address(masm->isolate()))); | 4712 __ li(a2, Operand(ExternalReference::isolate_address(isolate()))); |
4718 | 4713 |
4719 AllowExternalCallThatCantCauseGC scope(masm); | 4714 AllowExternalCallThatCantCauseGC scope(masm); |
4720 __ CallCFunction( | 4715 __ CallCFunction( |
4721 ExternalReference::incremental_marking_record_write_function( | 4716 ExternalReference::incremental_marking_record_write_function(isolate()), |
4722 masm->isolate()), | |
4723 argument_count); | 4717 argument_count); |
4724 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); | 4718 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); |
4725 } | 4719 } |
4726 | 4720 |
4727 | 4721 |
4728 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( | 4722 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( |
4729 MacroAssembler* masm, | 4723 MacroAssembler* masm, |
4730 OnNoNeedToInformIncrementalMarker on_no_need, | 4724 OnNoNeedToInformIncrementalMarker on_no_need, |
4731 Mode mode) { | 4725 Mode mode) { |
4732 Label on_black; | 4726 Label on_black; |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4872 // Array literal has ElementsKind of FAST_*_DOUBLE_ELEMENTS. | 4866 // Array literal has ElementsKind of FAST_*_DOUBLE_ELEMENTS. |
4873 __ bind(&double_elements); | 4867 __ bind(&double_elements); |
4874 __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset)); | 4868 __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset)); |
4875 __ StoreNumberToDoubleElements(a0, a3, t1, t3, t5, a2, &slow_elements); | 4869 __ StoreNumberToDoubleElements(a0, a3, t1, t3, t5, a2, &slow_elements); |
4876 __ Ret(USE_DELAY_SLOT); | 4870 __ Ret(USE_DELAY_SLOT); |
4877 __ mov(v0, a0); | 4871 __ mov(v0, a0); |
4878 } | 4872 } |
4879 | 4873 |
4880 | 4874 |
4881 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { | 4875 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { |
4882 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); | 4876 CEntryStub ces(isolate(), 1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); |
4883 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | 4877 __ Call(ces.GetCode(isolate()), RelocInfo::CODE_TARGET); |
4884 int parameter_count_offset = | 4878 int parameter_count_offset = |
4885 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | 4879 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
4886 __ lw(a1, MemOperand(fp, parameter_count_offset)); | 4880 __ lw(a1, MemOperand(fp, parameter_count_offset)); |
4887 if (function_mode_ == JS_FUNCTION_STUB_MODE) { | 4881 if (function_mode_ == JS_FUNCTION_STUB_MODE) { |
4888 __ Addu(a1, a1, Operand(1)); | 4882 __ Addu(a1, a1, Operand(1)); |
4889 } | 4883 } |
4890 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4884 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
4891 __ sll(a1, a1, kPointerSizeLog2); | 4885 __ sll(a1, a1, kPointerSizeLog2); |
4892 __ Ret(USE_DELAY_SLOT); | 4886 __ Ret(USE_DELAY_SLOT); |
4893 __ Addu(sp, sp, a1); | 4887 __ Addu(sp, sp, a1); |
4894 } | 4888 } |
4895 | 4889 |
4896 | 4890 |
4897 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4891 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
4898 if (masm->isolate()->function_entry_hook() != NULL) { | 4892 if (masm->isolate()->function_entry_hook() != NULL) { |
4899 ProfileEntryHookStub stub; | 4893 ProfileEntryHookStub stub(masm->isolate()); |
4900 __ push(ra); | 4894 __ push(ra); |
4901 __ CallStub(&stub); | 4895 __ CallStub(&stub); |
4902 __ pop(ra); | 4896 __ pop(ra); |
4903 } | 4897 } |
4904 } | 4898 } |
4905 | 4899 |
4906 | 4900 |
4907 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 4901 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { |
4908 // The entry hook is a "push ra" instruction, followed by a call. | 4902 // The entry hook is a "push ra" instruction, followed by a call. |
4909 // Note: on MIPS "push" is 2 instruction | 4903 // Note: on MIPS "push" is 2 instruction |
(...skipping 21 matching lines...) Expand all Loading... |
4931 // Align the stack if necessary. | 4925 // Align the stack if necessary. |
4932 int frame_alignment = masm->ActivationFrameAlignment(); | 4926 int frame_alignment = masm->ActivationFrameAlignment(); |
4933 if (frame_alignment > kPointerSize) { | 4927 if (frame_alignment > kPointerSize) { |
4934 __ mov(s5, sp); | 4928 __ mov(s5, sp); |
4935 ASSERT(IsPowerOf2(frame_alignment)); | 4929 ASSERT(IsPowerOf2(frame_alignment)); |
4936 __ And(sp, sp, Operand(-frame_alignment)); | 4930 __ And(sp, sp, Operand(-frame_alignment)); |
4937 } | 4931 } |
4938 __ Subu(sp, sp, kCArgsSlotsSize); | 4932 __ Subu(sp, sp, kCArgsSlotsSize); |
4939 #if defined(V8_HOST_ARCH_MIPS) | 4933 #if defined(V8_HOST_ARCH_MIPS) |
4940 int32_t entry_hook = | 4934 int32_t entry_hook = |
4941 reinterpret_cast<int32_t>(masm->isolate()->function_entry_hook()); | 4935 reinterpret_cast<int32_t>(isolate()->function_entry_hook()); |
4942 __ li(t9, Operand(entry_hook)); | 4936 __ li(t9, Operand(entry_hook)); |
4943 #else | 4937 #else |
4944 // Under the simulator we need to indirect the entry hook through a | 4938 // Under the simulator we need to indirect the entry hook through a |
4945 // trampoline function at a known address. | 4939 // trampoline function at a known address. |
4946 // It additionally takes an isolate as a third parameter. | 4940 // It additionally takes an isolate as a third parameter. |
4947 __ li(a2, Operand(ExternalReference::isolate_address(masm->isolate()))); | 4941 __ li(a2, Operand(ExternalReference::isolate_address(isolate()))); |
4948 | 4942 |
4949 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); | 4943 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); |
4950 __ li(t9, Operand(ExternalReference(&dispatcher, | 4944 __ li(t9, Operand(ExternalReference(&dispatcher, |
4951 ExternalReference::BUILTIN_CALL, | 4945 ExternalReference::BUILTIN_CALL, |
4952 masm->isolate()))); | 4946 isolate()))); |
4953 #endif | 4947 #endif |
4954 // Call C function through t9 to conform ABI for PIC. | 4948 // Call C function through t9 to conform ABI for PIC. |
4955 __ Call(t9); | 4949 __ Call(t9); |
4956 | 4950 |
4957 // Restore the stack pointer if needed. | 4951 // Restore the stack pointer if needed. |
4958 if (frame_alignment > kPointerSize) { | 4952 if (frame_alignment > kPointerSize) { |
4959 __ mov(sp, s5); | 4953 __ mov(sp, s5); |
4960 } else { | 4954 } else { |
4961 __ Addu(sp, sp, kCArgsSlotsSize); | 4955 __ Addu(sp, sp, kCArgsSlotsSize); |
4962 } | 4956 } |
4963 | 4957 |
4964 // Also pop ra to get Ret(0). | 4958 // Also pop ra to get Ret(0). |
4965 __ MultiPop(kSavedRegs | ra.bit()); | 4959 __ MultiPop(kSavedRegs | ra.bit()); |
4966 __ Ret(); | 4960 __ Ret(); |
4967 } | 4961 } |
4968 | 4962 |
4969 | 4963 |
4970 template<class T> | 4964 template<class T> |
4971 static void CreateArrayDispatch(MacroAssembler* masm, | 4965 static void CreateArrayDispatch(MacroAssembler* masm, |
4972 AllocationSiteOverrideMode mode) { | 4966 AllocationSiteOverrideMode mode) { |
4973 if (mode == DISABLE_ALLOCATION_SITES) { | 4967 if (mode == DISABLE_ALLOCATION_SITES) { |
4974 T stub(GetInitialFastElementsKind(), mode); | 4968 T stub(masm->isolate(), GetInitialFastElementsKind(), mode); |
4975 __ TailCallStub(&stub); | 4969 __ TailCallStub(&stub); |
4976 } else if (mode == DONT_OVERRIDE) { | 4970 } else if (mode == DONT_OVERRIDE) { |
4977 int last_index = GetSequenceIndexFromFastElementsKind( | 4971 int last_index = GetSequenceIndexFromFastElementsKind( |
4978 TERMINAL_FAST_ELEMENTS_KIND); | 4972 TERMINAL_FAST_ELEMENTS_KIND); |
4979 for (int i = 0; i <= last_index; ++i) { | 4973 for (int i = 0; i <= last_index; ++i) { |
4980 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 4974 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
4981 T stub(kind); | 4975 T stub(masm->isolate(), kind); |
4982 __ TailCallStub(&stub, eq, a3, Operand(kind)); | 4976 __ TailCallStub(&stub, eq, a3, Operand(kind)); |
4983 } | 4977 } |
4984 | 4978 |
4985 // If we reached this point there is a problem. | 4979 // If we reached this point there is a problem. |
4986 __ Abort(kUnexpectedElementsKindInArrayConstructor); | 4980 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
4987 } else { | 4981 } else { |
4988 UNREACHABLE(); | 4982 UNREACHABLE(); |
4989 } | 4983 } |
4990 } | 4984 } |
4991 | 4985 |
(...skipping 20 matching lines...) Expand all Loading... |
5012 } | 5006 } |
5013 | 5007 |
5014 // look at the first argument | 5008 // look at the first argument |
5015 __ lw(t1, MemOperand(sp, 0)); | 5009 __ lw(t1, MemOperand(sp, 0)); |
5016 __ Branch(&normal_sequence, eq, t1, Operand(zero_reg)); | 5010 __ Branch(&normal_sequence, eq, t1, Operand(zero_reg)); |
5017 | 5011 |
5018 if (mode == DISABLE_ALLOCATION_SITES) { | 5012 if (mode == DISABLE_ALLOCATION_SITES) { |
5019 ElementsKind initial = GetInitialFastElementsKind(); | 5013 ElementsKind initial = GetInitialFastElementsKind(); |
5020 ElementsKind holey_initial = GetHoleyElementsKind(initial); | 5014 ElementsKind holey_initial = GetHoleyElementsKind(initial); |
5021 | 5015 |
5022 ArraySingleArgumentConstructorStub stub_holey(holey_initial, | 5016 ArraySingleArgumentConstructorStub stub_holey(masm->isolate(), |
| 5017 holey_initial, |
5023 DISABLE_ALLOCATION_SITES); | 5018 DISABLE_ALLOCATION_SITES); |
5024 __ TailCallStub(&stub_holey); | 5019 __ TailCallStub(&stub_holey); |
5025 | 5020 |
5026 __ bind(&normal_sequence); | 5021 __ bind(&normal_sequence); |
5027 ArraySingleArgumentConstructorStub stub(initial, | 5022 ArraySingleArgumentConstructorStub stub(masm->isolate(), |
| 5023 initial, |
5028 DISABLE_ALLOCATION_SITES); | 5024 DISABLE_ALLOCATION_SITES); |
5029 __ TailCallStub(&stub); | 5025 __ TailCallStub(&stub); |
5030 } else if (mode == DONT_OVERRIDE) { | 5026 } else if (mode == DONT_OVERRIDE) { |
5031 // We are going to create a holey array, but our kind is non-holey. | 5027 // We are going to create a holey array, but our kind is non-holey. |
5032 // Fix kind and retry (only if we have an allocation site in the slot). | 5028 // Fix kind and retry (only if we have an allocation site in the slot). |
5033 __ Addu(a3, a3, Operand(1)); | 5029 __ Addu(a3, a3, Operand(1)); |
5034 | 5030 |
5035 if (FLAG_debug_code) { | 5031 if (FLAG_debug_code) { |
5036 __ lw(t1, FieldMemOperand(a2, 0)); | 5032 __ lw(t1, FieldMemOperand(a2, 0)); |
5037 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); | 5033 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); |
5038 __ Assert(eq, kExpectedAllocationSite, t1, Operand(at)); | 5034 __ Assert(eq, kExpectedAllocationSite, t1, Operand(at)); |
5039 } | 5035 } |
5040 | 5036 |
5041 // Save the resulting elements kind in type info. We can't just store a3 | 5037 // Save the resulting elements kind in type info. We can't just store a3 |
5042 // in the AllocationSite::transition_info field because elements kind is | 5038 // in the AllocationSite::transition_info field because elements kind is |
5043 // restricted to a portion of the field...upper bits need to be left alone. | 5039 // restricted to a portion of the field...upper bits need to be left alone. |
5044 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); | 5040 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); |
5045 __ lw(t0, FieldMemOperand(a2, AllocationSite::kTransitionInfoOffset)); | 5041 __ lw(t0, FieldMemOperand(a2, AllocationSite::kTransitionInfoOffset)); |
5046 __ Addu(t0, t0, Operand(Smi::FromInt(kFastElementsKindPackedToHoley))); | 5042 __ Addu(t0, t0, Operand(Smi::FromInt(kFastElementsKindPackedToHoley))); |
5047 __ sw(t0, FieldMemOperand(a2, AllocationSite::kTransitionInfoOffset)); | 5043 __ sw(t0, FieldMemOperand(a2, AllocationSite::kTransitionInfoOffset)); |
5048 | 5044 |
5049 | 5045 |
5050 __ bind(&normal_sequence); | 5046 __ bind(&normal_sequence); |
5051 int last_index = GetSequenceIndexFromFastElementsKind( | 5047 int last_index = GetSequenceIndexFromFastElementsKind( |
5052 TERMINAL_FAST_ELEMENTS_KIND); | 5048 TERMINAL_FAST_ELEMENTS_KIND); |
5053 for (int i = 0; i <= last_index; ++i) { | 5049 for (int i = 0; i <= last_index; ++i) { |
5054 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 5050 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
5055 ArraySingleArgumentConstructorStub stub(kind); | 5051 ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); |
5056 __ TailCallStub(&stub, eq, a3, Operand(kind)); | 5052 __ TailCallStub(&stub, eq, a3, Operand(kind)); |
5057 } | 5053 } |
5058 | 5054 |
5059 // If we reached this point there is a problem. | 5055 // If we reached this point there is a problem. |
5060 __ Abort(kUnexpectedElementsKindInArrayConstructor); | 5056 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
5061 } else { | 5057 } else { |
5062 UNREACHABLE(); | 5058 UNREACHABLE(); |
5063 } | 5059 } |
5064 } | 5060 } |
5065 | 5061 |
5066 | 5062 |
5067 template<class T> | 5063 template<class T> |
5068 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 5064 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
5069 int to_index = GetSequenceIndexFromFastElementsKind( | 5065 int to_index = GetSequenceIndexFromFastElementsKind( |
5070 TERMINAL_FAST_ELEMENTS_KIND); | 5066 TERMINAL_FAST_ELEMENTS_KIND); |
5071 for (int i = 0; i <= to_index; ++i) { | 5067 for (int i = 0; i <= to_index; ++i) { |
5072 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 5068 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
5073 T stub(kind); | 5069 T stub(isolate, kind); |
5074 stub.GetCode(isolate); | 5070 stub.GetCode(isolate); |
5075 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { | 5071 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { |
5076 T stub1(kind, DISABLE_ALLOCATION_SITES); | 5072 T stub1(isolate, kind, DISABLE_ALLOCATION_SITES); |
5077 stub1.GetCode(isolate); | 5073 stub1.GetCode(isolate); |
5078 } | 5074 } |
5079 } | 5075 } |
5080 } | 5076 } |
5081 | 5077 |
5082 | 5078 |
5083 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 5079 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
5084 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 5080 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
5085 isolate); | 5081 isolate); |
5086 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( | 5082 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( |
5087 isolate); | 5083 isolate); |
5088 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( | 5084 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( |
5089 isolate); | 5085 isolate); |
5090 } | 5086 } |
5091 | 5087 |
5092 | 5088 |
5093 void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( | 5089 void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( |
5094 Isolate* isolate) { | 5090 Isolate* isolate) { |
5095 ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS }; | 5091 ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS }; |
5096 for (int i = 0; i < 2; i++) { | 5092 for (int i = 0; i < 2; i++) { |
5097 // For internal arrays we only need a few things. | 5093 // For internal arrays we only need a few things. |
5098 InternalArrayNoArgumentConstructorStub stubh1(kinds[i]); | 5094 InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]); |
5099 stubh1.GetCode(isolate); | 5095 stubh1.GetCode(isolate); |
5100 InternalArraySingleArgumentConstructorStub stubh2(kinds[i]); | 5096 InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]); |
5101 stubh2.GetCode(isolate); | 5097 stubh2.GetCode(isolate); |
5102 InternalArrayNArgumentsConstructorStub stubh3(kinds[i]); | 5098 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); |
5103 stubh3.GetCode(isolate); | 5099 stubh3.GetCode(isolate); |
5104 } | 5100 } |
5105 } | 5101 } |
5106 | 5102 |
5107 | 5103 |
5108 void ArrayConstructorStub::GenerateDispatchToArrayStub( | 5104 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
5109 MacroAssembler* masm, | 5105 MacroAssembler* masm, |
5110 AllocationSiteOverrideMode mode) { | 5106 AllocationSiteOverrideMode mode) { |
5111 if (argument_count_ == ANY) { | 5107 if (argument_count_ == ANY) { |
5112 Label not_zero_case, not_one_case; | 5108 Label not_zero_case, not_one_case; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5171 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); | 5167 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
5172 | 5168 |
5173 __ bind(&no_info); | 5169 __ bind(&no_info); |
5174 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); | 5170 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); |
5175 } | 5171 } |
5176 | 5172 |
5177 | 5173 |
5178 void InternalArrayConstructorStub::GenerateCase( | 5174 void InternalArrayConstructorStub::GenerateCase( |
5179 MacroAssembler* masm, ElementsKind kind) { | 5175 MacroAssembler* masm, ElementsKind kind) { |
5180 | 5176 |
5181 InternalArrayNoArgumentConstructorStub stub0(kind); | 5177 InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); |
5182 __ TailCallStub(&stub0, lo, a0, Operand(1)); | 5178 __ TailCallStub(&stub0, lo, a0, Operand(1)); |
5183 | 5179 |
5184 InternalArrayNArgumentsConstructorStub stubN(kind); | 5180 InternalArrayNArgumentsConstructorStub stubN(isolate(), kind); |
5185 __ TailCallStub(&stubN, hi, a0, Operand(1)); | 5181 __ TailCallStub(&stubN, hi, a0, Operand(1)); |
5186 | 5182 |
5187 if (IsFastPackedElementsKind(kind)) { | 5183 if (IsFastPackedElementsKind(kind)) { |
5188 // We might need to create a holey array | 5184 // We might need to create a holey array |
5189 // look at the first argument. | 5185 // look at the first argument. |
5190 __ lw(at, MemOperand(sp, 0)); | 5186 __ lw(at, MemOperand(sp, 0)); |
5191 | 5187 |
5192 InternalArraySingleArgumentConstructorStub | 5188 InternalArraySingleArgumentConstructorStub |
5193 stub1_holey(GetHoleyElementsKind(kind)); | 5189 stub1_holey(isolate(), GetHoleyElementsKind(kind)); |
5194 __ TailCallStub(&stub1_holey, ne, at, Operand(zero_reg)); | 5190 __ TailCallStub(&stub1_holey, ne, at, Operand(zero_reg)); |
5195 } | 5191 } |
5196 | 5192 |
5197 InternalArraySingleArgumentConstructorStub stub1(kind); | 5193 InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); |
5198 __ TailCallStub(&stub1); | 5194 __ TailCallStub(&stub1); |
5199 } | 5195 } |
5200 | 5196 |
5201 | 5197 |
5202 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { | 5198 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { |
5203 // ----------- S t a t e ------------- | 5199 // ----------- S t a t e ------------- |
5204 // -- a0 : argc | 5200 // -- a0 : argc |
5205 // -- a1 : constructor | 5201 // -- a1 : constructor |
5206 // -- sp[0] : return address | 5202 // -- sp[0] : return address |
5207 // -- sp[4] : last argument | 5203 // -- sp[4] : last argument |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5277 | 5273 |
5278 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 5274 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
5279 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 5275 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
5280 STATIC_ASSERT(FCA::kDataIndex == 4); | 5276 STATIC_ASSERT(FCA::kDataIndex == 4); |
5281 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 5277 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
5282 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 5278 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
5283 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 5279 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
5284 STATIC_ASSERT(FCA::kHolderIndex == 0); | 5280 STATIC_ASSERT(FCA::kHolderIndex == 0); |
5285 STATIC_ASSERT(FCA::kArgsLength == 7); | 5281 STATIC_ASSERT(FCA::kArgsLength == 7); |
5286 | 5282 |
5287 Isolate* isolate = masm->isolate(); | |
5288 | |
5289 // Save context, callee and call data. | 5283 // Save context, callee and call data. |
5290 __ Push(context, callee, call_data); | 5284 __ Push(context, callee, call_data); |
5291 // Load context from callee. | 5285 // Load context from callee. |
5292 __ lw(context, FieldMemOperand(callee, JSFunction::kContextOffset)); | 5286 __ lw(context, FieldMemOperand(callee, JSFunction::kContextOffset)); |
5293 | 5287 |
5294 Register scratch = call_data; | 5288 Register scratch = call_data; |
5295 if (!call_data_undefined) { | 5289 if (!call_data_undefined) { |
5296 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 5290 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
5297 } | 5291 } |
5298 // Push return value and default return value. | 5292 // Push return value and default return value. |
5299 __ Push(scratch, scratch); | 5293 __ Push(scratch, scratch); |
5300 __ li(scratch, | 5294 __ li(scratch, |
5301 Operand(ExternalReference::isolate_address(isolate))); | 5295 Operand(ExternalReference::isolate_address(isolate()))); |
5302 // Push isolate and holder. | 5296 // Push isolate and holder. |
5303 __ Push(scratch, holder); | 5297 __ Push(scratch, holder); |
5304 | 5298 |
5305 // Prepare arguments. | 5299 // Prepare arguments. |
5306 __ mov(scratch, sp); | 5300 __ mov(scratch, sp); |
5307 | 5301 |
5308 // Allocate the v8::Arguments structure in the arguments' space since | 5302 // Allocate the v8::Arguments structure in the arguments' space since |
5309 // it's not controlled by GC. | 5303 // it's not controlled by GC. |
5310 const int kApiStackSpace = 4; | 5304 const int kApiStackSpace = 4; |
5311 | 5305 |
(...skipping 13 matching lines...) Expand all Loading... |
5325 __ li(at, Operand(argc)); | 5319 __ li(at, Operand(argc)); |
5326 __ sw(at, MemOperand(a0, 2 * kPointerSize)); | 5320 __ sw(at, MemOperand(a0, 2 * kPointerSize)); |
5327 // FunctionCallbackInfo::is_construct_call = 0 | 5321 // FunctionCallbackInfo::is_construct_call = 0 |
5328 __ sw(zero_reg, MemOperand(a0, 3 * kPointerSize)); | 5322 __ sw(zero_reg, MemOperand(a0, 3 * kPointerSize)); |
5329 | 5323 |
5330 const int kStackUnwindSpace = argc + FCA::kArgsLength + 1; | 5324 const int kStackUnwindSpace = argc + FCA::kArgsLength + 1; |
5331 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); | 5325 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); |
5332 ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL; | 5326 ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL; |
5333 ApiFunction thunk_fun(thunk_address); | 5327 ApiFunction thunk_fun(thunk_address); |
5334 ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, | 5328 ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, |
5335 masm->isolate()); | 5329 isolate()); |
5336 | 5330 |
5337 AllowExternalCallThatCantCauseGC scope(masm); | 5331 AllowExternalCallThatCantCauseGC scope(masm); |
5338 MemOperand context_restore_operand( | 5332 MemOperand context_restore_operand( |
5339 fp, (2 + FCA::kContextSaveIndex) * kPointerSize); | 5333 fp, (2 + FCA::kContextSaveIndex) * kPointerSize); |
5340 // Stores return the first js argument. | 5334 // Stores return the first js argument. |
5341 int return_value_offset = 0; | 5335 int return_value_offset = 0; |
5342 if (is_store) { | 5336 if (is_store) { |
5343 return_value_offset = 2 + FCA::kArgsLength; | 5337 return_value_offset = 2 + FCA::kArgsLength; |
5344 } else { | 5338 } else { |
5345 return_value_offset = 2 + FCA::kReturnValueOffset; | 5339 return_value_offset = 2 + FCA::kReturnValueOffset; |
(...skipping 30 matching lines...) Expand all Loading... |
5376 __ sw(a1, MemOperand(sp, 1 * kPointerSize)); | 5370 __ sw(a1, MemOperand(sp, 1 * kPointerSize)); |
5377 __ Addu(a1, sp, Operand(1 * kPointerSize)); // a1 = AccessorInfo& | 5371 __ Addu(a1, sp, Operand(1 * kPointerSize)); // a1 = AccessorInfo& |
5378 | 5372 |
5379 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; | 5373 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; |
5380 | 5374 |
5381 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); | 5375 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); |
5382 ExternalReference::Type thunk_type = | 5376 ExternalReference::Type thunk_type = |
5383 ExternalReference::PROFILING_GETTER_CALL; | 5377 ExternalReference::PROFILING_GETTER_CALL; |
5384 ApiFunction thunk_fun(thunk_address); | 5378 ApiFunction thunk_fun(thunk_address); |
5385 ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, | 5379 ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, |
5386 masm->isolate()); | 5380 isolate()); |
5387 __ CallApiFunctionAndReturn(api_function_address, | 5381 __ CallApiFunctionAndReturn(api_function_address, |
5388 thunk_ref, | 5382 thunk_ref, |
5389 kStackUnwindSpace, | 5383 kStackUnwindSpace, |
5390 MemOperand(fp, 6 * kPointerSize), | 5384 MemOperand(fp, 6 * kPointerSize), |
5391 NULL); | 5385 NULL); |
5392 } | 5386 } |
5393 | 5387 |
5394 | 5388 |
5395 #undef __ | 5389 #undef __ |
5396 | 5390 |
5397 } } // namespace v8::internal | 5391 } } // namespace v8::internal |
5398 | 5392 |
5399 #endif // V8_TARGET_ARCH_MIPS | 5393 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |