Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 8932004: Implement target cache for constructor calls. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 4555 matching lines...) Expand 10 before | Expand all | Expand 10 after
4566 __ cmp(scratch, kSymbolTag | kStringTag); 4566 __ cmp(scratch, kSymbolTag | kStringTag);
4567 __ j(not_equal, label); 4567 __ j(not_equal, label);
4568 } 4568 }
4569 4569
4570 4570
4571 void StackCheckStub::Generate(MacroAssembler* masm) { 4571 void StackCheckStub::Generate(MacroAssembler* masm) {
4572 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); 4572 __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
4573 } 4573 }
4574 4574
4575 4575
4576 void CallFunctionStub::FinishCode(Handle<Code> code) { 4576 void CallStub::Clear(Heap* heap, Address address) {
Vyacheslav Egorov (Chromium) 2012/01/23 10:39:52 Did it disappear? I can't find it.
Michael Starzinger 2012/01/25 11:42:29 Done. It was still there on line 4633. No longer n
4577 code->set_has_function_cache(RecordCallTarget());
4578 }
4579
4580
4581 void CallFunctionStub::Clear(Heap* heap, Address address) {
4582 ASSERT(Memory::uint8_at(address + kPointerSize) == Assembler::kTestEaxByte); 4577 ASSERT(Memory::uint8_at(address + kPointerSize) == Assembler::kTestEaxByte);
4583 // 1 ~ size of the test eax opcode. 4578 // 1 ~ size of the test eax opcode.
4584 Object* cell = Memory::Object_at(address + kPointerSize + 1); 4579 Object* cell = Memory::Object_at(address + kPointerSize + 1);
4585 // Low-level because clearing happens during GC. 4580 // Low-level because clearing happens during GC.
4586 reinterpret_cast<JSGlobalPropertyCell*>(cell)->set_value( 4581 reinterpret_cast<JSGlobalPropertyCell*>(cell)->set_value(
4587 RawUninitializedSentinel(heap)); 4582 RawUninitializedSentinel(heap));
4588 } 4583 }
4589 4584
4590 4585
4591 Object* CallFunctionStub::GetCachedValue(Address address) { 4586 Object* CallStub::GetCachedValue(Address address) {
4592 ASSERT(Memory::uint8_at(address + kPointerSize) == Assembler::kTestEaxByte); 4587 ASSERT(Memory::uint8_at(address + kPointerSize) == Assembler::kTestEaxByte);
4593 // 1 ~ size of the test eax opcode. 4588 // 1 ~ size of the test eax opcode.
4594 Object* cell = Memory::Object_at(address + kPointerSize + 1); 4589 Object* cell = Memory::Object_at(address + kPointerSize + 1);
4595 return JSGlobalPropertyCell::cast(cell)->value(); 4590 return JSGlobalPropertyCell::cast(cell)->value();
4596 } 4591 }
4597 4592
4598 4593
4594 void CallStub::GenerateRecordCallTarget(MacroAssembler* masm) {
4595 // Cache the called function in a global property cell in the
4596 // instruction stream after the call. Cache states are uninitialized,
4597 // monomorphic (indicated by a JSFunction), and megamorphic.
4598 // edi : the function to call
4599 Isolate* isolate = masm->isolate();
4600 Label initialize, call;
Vyacheslav Egorov (Chromium) 2012/01/23 10:39:52 I would rename call to done.
Michael Starzinger 2012/01/25 11:42:29 Done.
4601
4602 // Load the cache cell address into ebx and the cache state into ecx.
4603 __ mov(ebx, Operand(esp, 0)); // Return address.
4604 __ mov(ebx, Operand(ebx, 1)); // 1 ~ sizeof 'test eax' opcode in bytes.
Vyacheslav Egorov (Chromium) 2012/01/23 10:39:52 you can generate assertion into instruction stream
Michael Starzinger 2012/01/25 11:42:29 Done. No longer needed with new approach.
4605 __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
4606
4607 // A monomorphic cache hit or an already megamorphic state: invoke the
4608 // function without changing the state.
4609 __ cmp(ecx, edi);
4610 __ j(equal, &call, Label::kNear);
4611 __ cmp(ecx, Immediate(MegamorphicSentinel(isolate)));
4612 __ j(equal, &call, Label::kNear);
4613
4614 // A monomorphic miss (i.e, here the cache is not uninitialized) goes
4615 // megamorphic.
4616 __ cmp(ecx, Immediate(UninitializedSentinel(isolate)));
4617 __ j(equal, &initialize, Label::kNear);
4618 // MegamorphicSentinel is an immortal immovable object (undefined) so no
4619 // write-barrier is needed.
4620 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
4621 Immediate(MegamorphicSentinel(isolate)));
4622 __ jmp(&call, Label::kNear);
4623
4624 // An uninitialized cache is patched with the function.
4625 __ bind(&initialize);
4626 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi);
4627 // No need for a write barrier here - cells are rescanned.
4628
4629 __ bind(&call);
4630 }
4631
4632
4633 void CallFunctionStub::FinishCode(Handle<Code> code) {
4634 code->set_has_function_cache(RecordCallTarget());
4635 }
4636
4637
4599 void CallFunctionStub::Generate(MacroAssembler* masm) { 4638 void CallFunctionStub::Generate(MacroAssembler* masm) {
4600 // edi : the function to call 4639 // edi : the function to call
4601 Isolate* isolate = masm->isolate(); 4640 Isolate* isolate = masm->isolate();
4602 Label slow, non_function; 4641 Label slow, non_function;
4603 4642
4604 // The receiver might implicitly be the global object. This is 4643 // The receiver might implicitly be the global object. This is
4605 // indicated by passing the hole as the receiver to the call 4644 // indicated by passing the hole as the receiver to the call
4606 // function stub. 4645 // function stub.
4607 if (ReceiverMightBeImplicit()) { 4646 if (ReceiverMightBeImplicit()) {
4608 Label receiver_ok; 4647 Label receiver_ok;
(...skipping 10 matching lines...) Expand all
4619 __ bind(&receiver_ok); 4658 __ bind(&receiver_ok);
4620 } 4659 }
4621 4660
4622 // Check that the function really is a JavaScript function. 4661 // Check that the function really is a JavaScript function.
4623 __ JumpIfSmi(edi, &non_function); 4662 __ JumpIfSmi(edi, &non_function);
4624 // Goto slow case if we do not have a function. 4663 // Goto slow case if we do not have a function.
4625 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 4664 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
4626 __ j(not_equal, &slow); 4665 __ j(not_equal, &slow);
4627 4666
4628 if (RecordCallTarget()) { 4667 if (RecordCallTarget()) {
4629 // Cache the called function in a global property cell in the 4668 GenerateRecordCallTarget(masm);
4630 // instruction stream after the call. Cache states are uninitialized,
4631 // monomorphic (indicated by a JSFunction), and megamorphic.
4632 Label initialize, call;
4633 // Load the cache cell address into ebx and the cache state into ecx.
4634 __ mov(ebx, Operand(esp, 0)); // Return address.
4635 __ mov(ebx, Operand(ebx, 1)); // 1 ~ sizeof 'test eax' opcode in bytes.
4636 __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
4637
4638 // A monomorphic cache hit or an already megamorphic state: invoke the
4639 // function without changing the state.
4640 __ cmp(ecx, edi);
4641 __ j(equal, &call, Label::kNear);
4642 __ cmp(ecx, Immediate(MegamorphicSentinel(isolate)));
4643 __ j(equal, &call, Label::kNear);
4644
4645 // A monomorphic miss (i.e, here the cache is not uninitialized) goes
4646 // megamorphic.
4647 __ cmp(ecx, Immediate(UninitializedSentinel(isolate)));
4648 __ j(equal, &initialize, Label::kNear);
4649 // MegamorphicSentinel is an immortal immovable object (undefined) so no
4650 // write-barrier is needed.
4651 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
4652 Immediate(MegamorphicSentinel(isolate)));
4653 __ jmp(&call, Label::kNear);
4654
4655 // An uninitialized cache is patched with the function.
4656 __ bind(&initialize);
4657 __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi);
4658 // No need for a write barrier here - cells are rescanned.
4659
4660 __ bind(&call);
4661 } 4669 }
4662 4670
4663 // Fast-case: Just invoke the function. 4671 // Fast-case: Just invoke the function.
4664 ParameterCount actual(argc_); 4672 ParameterCount actual(argc_);
4665 4673
4666 if (ReceiverMightBeImplicit()) { 4674 if (ReceiverMightBeImplicit()) {
4667 Label call_as_function; 4675 Label call_as_function;
4668 __ cmp(eax, isolate->factory()->the_hole_value()); 4676 __ cmp(eax, isolate->factory()->the_hole_value());
4669 __ j(equal, &call_as_function); 4677 __ j(equal, &call_as_function);
4670 __ InvokeFunction(edi, 4678 __ InvokeFunction(edi,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
4713 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); 4721 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi);
4714 __ Set(eax, Immediate(argc_)); 4722 __ Set(eax, Immediate(argc_));
4715 __ Set(ebx, Immediate(0)); 4723 __ Set(ebx, Immediate(0));
4716 __ SetCallKind(ecx, CALL_AS_METHOD); 4724 __ SetCallKind(ecx, CALL_AS_METHOD);
4717 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 4725 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
4718 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); 4726 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
4719 __ jmp(adaptor, RelocInfo::CODE_TARGET); 4727 __ jmp(adaptor, RelocInfo::CODE_TARGET);
4720 } 4728 }
4721 4729
4722 4730
4731 void CallConstructStub::FinishCode(Handle<Code> code) {
4732 code->set_has_function_cache(RecordCallTarget());
4733 }
4734
4735
4736 void CallConstructStub::Generate(MacroAssembler* masm) {
4737 // ----------- S t a t e -------------
4738 // -- eax: number of arguments
4739 // -- edi: constructor function
4740 // -----------------------------------
4741
4742 Label slow, non_function_call;
4743 // Check that function is not a smi.
4744 __ JumpIfSmi(edi, &non_function_call);
4745 // Check that function is a JSFunction.
4746 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
4747 __ j(not_equal, &slow);
4748
4749 if (RecordCallTarget()) {
4750 GenerateRecordCallTarget(masm);
4751 }
4752
4753 // Jump to the function-specific construct stub.
4754 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
4755 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset));
4756 __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize));
4757 __ jmp(ebx);
4758
4759 // edi: called object
4760 // eax: number of arguments
4761 // ecx: object map
4762 Label do_call;
4763 __ bind(&slow);
4764 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
4765 __ j(not_equal, &non_function_call);
4766 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
4767 __ jmp(&do_call);
4768
4769 __ bind(&non_function_call);
4770 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
4771 __ bind(&do_call);
4772 // Set expected number of arguments to zero (not changing eax).
4773 __ Set(ebx, Immediate(0));
4774 Handle<Code> arguments_adaptor =
4775 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
4776 __ SetCallKind(ecx, CALL_AS_METHOD);
4777 __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET);
4778 }
4779
4780
4723 bool CEntryStub::NeedsImmovableCode() { 4781 bool CEntryStub::NeedsImmovableCode() {
4724 return false; 4782 return false;
4725 } 4783 }
4726 4784
4727 4785
4728 bool CEntryStub::IsPregenerated() { 4786 bool CEntryStub::IsPregenerated() {
4729 return (!save_doubles_ || ISOLATE->fp_stubs_generated()) && 4787 return (!save_doubles_ || ISOLATE->fp_stubs_generated()) &&
4730 result_size_ == 1; 4788 result_size_ == 1;
4731 } 4789 }
4732 4790
(...skipping 2577 matching lines...) Expand 10 before | Expand all | Expand 10 after
7310 false); 7368 false);
7311 __ pop(edx); 7369 __ pop(edx);
7312 __ ret(0); 7370 __ ret(0);
7313 } 7371 }
7314 7372
7315 #undef __ 7373 #undef __
7316 7374
7317 } } // namespace v8::internal 7375 } } // namespace v8::internal
7318 7376
7319 #endif // V8_TARGET_ARCH_IA32 7377 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698