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 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 __ eor(result_reg, result_reg, Operand(scratch_high, ASR, 31)); | 686 __ eor(result_reg, result_reg, Operand(scratch_high, ASR, 31)); |
687 __ add(result_reg, result_reg, Operand(scratch_high, LSR, 31)); | 687 __ add(result_reg, result_reg, Operand(scratch_high, LSR, 31)); |
688 | 688 |
689 __ bind(&done); | 689 __ bind(&done); |
690 | 690 |
691 __ Pop(scratch_high, scratch_low); | 691 __ Pop(scratch_high, scratch_low); |
692 __ Ret(); | 692 __ Ret(); |
693 } | 693 } |
694 | 694 |
695 | 695 |
696 bool WriteInt32ToHeapNumberStub::IsPregenerated(Isolate* isolate) { | |
697 // These variants are compiled ahead of time. See next method. | |
698 if (the_int_.is(r1) && the_heap_number_.is(r0) && scratch_.is(r2)) { | |
699 return true; | |
700 } | |
701 if (the_int_.is(r2) && the_heap_number_.is(r0) && scratch_.is(r3)) { | |
702 return true; | |
703 } | |
704 // Other register combinations are generated as and when they are needed, | |
705 // so it is unsafe to call them from stubs (we can't generate a stub while | |
706 // we are generating a stub). | |
707 return false; | |
708 } | |
709 | |
710 | |
711 void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime( | 696 void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime( |
712 Isolate* isolate) { | 697 Isolate* isolate) { |
713 WriteInt32ToHeapNumberStub stub1(r1, r0, r2); | 698 WriteInt32ToHeapNumberStub stub1(r1, r0, r2); |
714 WriteInt32ToHeapNumberStub stub2(r2, r0, r3); | 699 WriteInt32ToHeapNumberStub stub2(r2, r0, r3); |
715 stub1.GetCode(isolate)->set_is_pregenerated(true); | 700 stub1.GetCode(isolate)->set_is_pregenerated(true); |
716 stub2.GetCode(isolate)->set_is_pregenerated(true); | 701 stub2.GetCode(isolate)->set_is_pregenerated(true); |
717 } | 702 } |
718 | 703 |
719 | 704 |
720 // See comment for class. | 705 // See comment for class. |
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1667 __ Ret(); | 1652 __ Ret(); |
1668 } | 1653 } |
1669 } | 1654 } |
1670 | 1655 |
1671 | 1656 |
1672 bool CEntryStub::NeedsImmovableCode() { | 1657 bool CEntryStub::NeedsImmovableCode() { |
1673 return true; | 1658 return true; |
1674 } | 1659 } |
1675 | 1660 |
1676 | 1661 |
1677 bool CEntryStub::IsPregenerated(Isolate* isolate) { | |
1678 return (!save_doubles_ || isolate->fp_stubs_generated()) && | |
1679 result_size_ == 1; | |
1680 } | |
1681 | |
1682 | |
1683 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 1662 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
1684 CEntryStub::GenerateAheadOfTime(isolate); | 1663 CEntryStub::GenerateAheadOfTime(isolate); |
1685 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); | 1664 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); |
1686 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 1665 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
1687 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 1666 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
1688 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); | |
1689 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | 1667 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); |
1690 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); | 1668 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); |
1691 BinaryOpStub::GenerateAheadOfTime(isolate); | 1669 BinaryOpStub::GenerateAheadOfTime(isolate); |
1692 } | 1670 } |
1693 | 1671 |
1694 | 1672 |
1695 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 1673 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
1696 SaveFPRegsMode mode = kSaveFPRegs; | 1674 SaveFPRegsMode mode = kSaveFPRegs; |
1697 CEntryStub save_doubles(1, mode); | 1675 CEntryStub save_doubles(1, mode); |
1698 StoreBufferOverflowStub stub(mode); | 1676 StoreBufferOverflowStub stub(mode); |
(...skipping 3641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5340 __ bind(&in_dictionary); | 5318 __ bind(&in_dictionary); |
5341 __ mov(result, Operand(1)); | 5319 __ mov(result, Operand(1)); |
5342 __ Ret(); | 5320 __ Ret(); |
5343 | 5321 |
5344 __ bind(¬_in_dictionary); | 5322 __ bind(¬_in_dictionary); |
5345 __ mov(result, Operand::Zero()); | 5323 __ mov(result, Operand::Zero()); |
5346 __ Ret(); | 5324 __ Ret(); |
5347 } | 5325 } |
5348 | 5326 |
5349 | 5327 |
5350 struct AheadOfTimeWriteBarrierStubList { | |
5351 Register object, value, address; | |
5352 RememberedSetAction action; | |
5353 }; | |
5354 | |
5355 | |
5356 #define REG(Name) { kRegister_ ## Name ## _Code } | |
5357 | |
5358 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { | |
5359 // Used in RegExpExecStub. | |
5360 { REG(r6), REG(r4), REG(r3), EMIT_REMEMBERED_SET }, | |
5361 // Used in CompileArrayPushCall. | |
5362 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. | |
5363 // Also used in KeyedStoreIC::GenerateGeneric. | |
5364 { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET }, | |
5365 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. | |
5366 { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET }, | |
5367 { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET }, | |
5368 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. | |
5369 { REG(r2), REG(r1), REG(r3), EMIT_REMEMBERED_SET }, | |
5370 { REG(r3), REG(r1), REG(r2), EMIT_REMEMBERED_SET }, | |
5371 // KeyedStoreStubCompiler::GenerateStoreFastElement. | |
5372 { REG(r3), REG(r2), REG(r4), EMIT_REMEMBERED_SET }, | |
5373 { REG(r2), REG(r3), REG(r4), EMIT_REMEMBERED_SET }, | |
5374 // ElementsTransitionGenerator::GenerateMapChangeElementTransition | |
5375 // and ElementsTransitionGenerator::GenerateSmiToDouble | |
5376 // and ElementsTransitionGenerator::GenerateDoubleToObject | |
5377 { REG(r2), REG(r3), REG(r9), EMIT_REMEMBERED_SET }, | |
5378 { REG(r2), REG(r3), REG(r9), OMIT_REMEMBERED_SET }, | |
5379 // ElementsTransitionGenerator::GenerateDoubleToObject | |
5380 { REG(r6), REG(r2), REG(r0), EMIT_REMEMBERED_SET }, | |
5381 { REG(r2), REG(r6), REG(r9), EMIT_REMEMBERED_SET }, | |
5382 // StoreArrayLiteralElementStub::Generate | |
5383 { REG(r5), REG(r0), REG(r6), EMIT_REMEMBERED_SET }, | |
5384 // FastNewClosureStub::Generate | |
5385 { REG(r2), REG(r4), REG(r1), EMIT_REMEMBERED_SET }, | |
5386 // StringAddStub::Generate | |
5387 { REG(r3), REG(r1), REG(r4), EMIT_REMEMBERED_SET }, | |
5388 { REG(r3), REG(r0), REG(r4), EMIT_REMEMBERED_SET }, | |
5389 // Null termination. | |
5390 { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET} | |
5391 }; | |
5392 | |
5393 #undef REG | |
5394 | |
5395 | |
5396 bool RecordWriteStub::IsPregenerated(Isolate* isolate) { | |
5397 for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; | |
5398 !entry->object.is(no_reg); | |
5399 entry++) { | |
5400 if (object_.is(entry->object) && | |
5401 value_.is(entry->value) && | |
5402 address_.is(entry->address) && | |
5403 remembered_set_action_ == entry->action && | |
5404 save_fp_regs_mode_ == kDontSaveFPRegs) { | |
5405 return true; | |
5406 } | |
5407 } | |
5408 return false; | |
5409 } | |
5410 | |
5411 | |
5412 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( | 5328 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( |
5413 Isolate* isolate) { | 5329 Isolate* isolate) { |
5414 StoreBufferOverflowStub stub1(kDontSaveFPRegs); | 5330 StoreBufferOverflowStub stub1(kDontSaveFPRegs); |
5415 stub1.GetCode(isolate)->set_is_pregenerated(true); | 5331 stub1.GetCode(isolate)->set_is_pregenerated(true); |
5416 // Hydrogen code stubs need stub2 at snapshot time. | 5332 // Hydrogen code stubs need stub2 at snapshot time. |
5417 StoreBufferOverflowStub stub2(kSaveFPRegs); | 5333 StoreBufferOverflowStub stub2(kSaveFPRegs); |
5418 stub2.GetCode(isolate)->set_is_pregenerated(true); | 5334 stub2.GetCode(isolate)->set_is_pregenerated(true); |
5419 } | 5335 } |
5420 | 5336 |
5421 | 5337 |
5422 void RecordWriteStub::GenerateFixedRegStubsAheadOfTime(Isolate* isolate) { | |
5423 for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; | |
5424 !entry->object.is(no_reg); | |
5425 entry++) { | |
5426 RecordWriteStub stub(entry->object, | |
5427 entry->value, | |
5428 entry->address, | |
5429 entry->action, | |
5430 kDontSaveFPRegs); | |
5431 stub.GetCode(isolate)->set_is_pregenerated(true); | |
5432 } | |
5433 } | |
5434 | |
5435 | |
5436 bool CodeStub::CanUseFPRegisters() { | 5338 bool CodeStub::CanUseFPRegisters() { |
5437 return true; // VFP2 is a base requirement for V8 | 5339 return true; // VFP2 is a base requirement for V8 |
5438 } | 5340 } |
5439 | 5341 |
5440 | 5342 |
5441 // Takes the input in 3 registers: address_ value_ and object_. A pointer to | 5343 // Takes the input in 3 registers: address_ value_ and object_. A pointer to |
5442 // the value has just been written into the object, now this stub makes sure | 5344 // the value has just been written into the object, now this stub makes sure |
5443 // we keep the GC informed. The word in the object where the value has been | 5345 // we keep the GC informed. The word in the object where the value has been |
5444 // written is in the address register. | 5346 // written is in the address register. |
5445 void RecordWriteStub::Generate(MacroAssembler* masm) { | 5347 void RecordWriteStub::Generate(MacroAssembler* masm) { |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5731 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 5633 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
5732 ParameterCount argument_count(r0); | 5634 ParameterCount argument_count(r0); |
5733 __ InvokeFunction( | 5635 __ InvokeFunction( |
5734 r1, argument_count, JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 5636 r1, argument_count, JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
5735 } | 5637 } |
5736 | 5638 |
5737 | 5639 |
5738 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 5640 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
5739 if (masm->isolate()->function_entry_hook() != NULL) { | 5641 if (masm->isolate()->function_entry_hook() != NULL) { |
5740 PredictableCodeSizeScope predictable(masm, 4 * Assembler::kInstrSize); | 5642 PredictableCodeSizeScope predictable(masm, 4 * Assembler::kInstrSize); |
5741 AllowStubCallsScope allow_stub_calls(masm, true); | |
5742 ProfileEntryHookStub stub; | 5643 ProfileEntryHookStub stub; |
5743 __ push(lr); | 5644 __ push(lr); |
5744 __ CallStub(&stub); | 5645 __ CallStub(&stub); |
5745 __ pop(lr); | 5646 __ pop(lr); |
5746 } | 5647 } |
5747 } | 5648 } |
5748 | 5649 |
5749 | 5650 |
5750 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 5651 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { |
5751 // The entry hook is a "push lr" instruction, followed by a call. | 5652 // The entry hook is a "push lr" instruction, followed by a call. |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6132 __ bind(&fast_elements_case); | 6033 __ bind(&fast_elements_case); |
6133 GenerateCase(masm, FAST_ELEMENTS); | 6034 GenerateCase(masm, FAST_ELEMENTS); |
6134 } | 6035 } |
6135 | 6036 |
6136 | 6037 |
6137 #undef __ | 6038 #undef __ |
6138 | 6039 |
6139 } } // namespace v8::internal | 6040 } } // namespace v8::internal |
6140 | 6041 |
6141 #endif // V8_TARGET_ARCH_ARM | 6042 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |